summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Application/CapsuleApp/CapsuleApp.c1
-rw-r--r--MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c2
-rw-r--r--MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c4
-rw-r--r--MdeModulePkg/Application/UiApp/FrontPageStrings.uni6
-rw-r--r--MdeModulePkg/Bus/Ata/AhciPei/AhciPeiPassThru.c4
-rw-r--r--MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c4
-rw-r--r--MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.c3
-rw-r--r--MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.h3
-rw-r--r--MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c34
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c27
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h38
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf10
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c10
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.c584
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.h191
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c2
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c1128
-rw-r--r--MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf37
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c2
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c37
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h2
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c29
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c2
-rw-r--r--MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h2
-rw-r--r--MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c10
-rw-r--r--MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c12
-rw-r--r--MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.c32
-rw-r--r--MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.h1
-rw-r--r--MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf1
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c4
-rw-r--r--MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h16
-rw-r--r--MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c5
-rw-r--r--MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h4
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c11
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c2
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c188
-rw-r--r--MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c8
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c13
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c8
-rw-r--r--MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.c13
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c178
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h56
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf7
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c136
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.h1336
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c5
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h9
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf5
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c4
-rw-r--r--MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.h1336
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c82
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h2
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf1
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c11
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c267
-rw-r--r--MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c331
-rw-r--r--MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c2
-rw-r--r--MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c13
-rw-r--r--MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c2
-rw-r--r--MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcEcm/UsbEcmFunction.c2
-rw-r--r--MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c2
-rw-r--r--MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c2
-rw-r--r--MdeModulePkg/Core/Dxe/DxeMain.h14
-rw-r--r--MdeModulePkg/Core/Dxe/DxeMain.inf2
-rw-r--r--MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c18
-rw-r--r--MdeModulePkg/Core/Dxe/Gcd/Gcd.c49
-rw-r--r--MdeModulePkg/Core/Dxe/Hand/Handle.c91
-rw-r--r--MdeModulePkg/Core/Dxe/Image/Image.c4
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/HeapGuard.c51
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/Imem.h16
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/Page.c37
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c27
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c38
-rw-r--r--MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c185
-rw-r--r--MdeModulePkg/Core/DxeIplPeim/DxeLoad.c22
-rw-r--r--MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c10
-rw-r--r--MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c8
-rw-r--r--MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c117
-rw-r--r--MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h29
-rw-r--r--MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c453
-rw-r--r--MdeModulePkg/Core/Pei/FwVol/FwVol.c12
-rw-r--r--MdeModulePkg/Core/Pei/Hob/Hob.c8
-rw-r--r--MdeModulePkg/Core/Pei/Memory/MemoryServices.c44
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.h76
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain.inf7
-rw-r--r--MdeModulePkg/Core/Pei/PeiMain/PeiMain.c19
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmCore.c64
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf1
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c175
-rw-r--r--MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf2
-rw-r--r--MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c17
-rw-r--r--MdeModulePkg/Include/Guid/ArmFfaRxTxBufferInfo.h31
-rw-r--r--MdeModulePkg/Include/Guid/DelayedDispatch.h47
-rw-r--r--MdeModulePkg/Include/Guid/MigratedFvInfo.h3
-rw-r--r--MdeModulePkg/Include/Guid/MmCommBuffer.h66
-rw-r--r--MdeModulePkg/Include/Guid/NVMeEventGroup.h16
-rw-r--r--MdeModulePkg/Include/Guid/SmmVariableCommon.h3
-rw-r--r--MdeModulePkg/Include/Library/BootLogoLib.h2
-rw-r--r--MdeModulePkg/Include/Library/CapsuleLib.h4
-rw-r--r--MdeModulePkg/Include/Library/DebugAgentLib.h2
-rw-r--r--MdeModulePkg/Include/Library/FileExplorerLib.h2
-rw-r--r--MdeModulePkg/Include/Library/SecurityManagementLib.h2
-rw-r--r--MdeModulePkg/Include/Library/TdxMeasurementLib.h85
-rw-r--r--MdeModulePkg/Include/Ppi/AtaPassThru.h4
-rw-r--r--MdeModulePkg/Include/Ppi/UfsHostControllerPlatformPpi.h97
-rw-r--r--MdeModulePkg/Include/Protocol/DisplayProtocol.h2
-rw-r--r--MdeModulePkg/Include/Protocol/FileExplorer.h2
-rw-r--r--MdeModulePkg/Include/Protocol/MediaSanitize.h173
-rw-r--r--MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h4
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c754
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.h52
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.c160
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf46
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.c193
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf48
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.c272
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.h54
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMapStmm.c321
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf43
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.c75
-rw-r--r--MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf44
-rw-r--r--MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.c55
-rw-r--r--MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c2
-rw-r--r--MdeModulePkg/Library/BootLogoLib/BootLogoLib.c229
-rw-r--r--MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf4
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h2
-rw-r--r--MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c4
-rw-r--r--MdeModulePkg/Library/BootManagerUiLib/BootManager.c30
-rw-r--r--MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf7
-rw-r--r--MdeModulePkg/Library/BrotliCustomDecompressLib/intrin.h9
-rw-r--r--MdeModulePkg/Library/BrotliCustomDecompressLib/memory.h9
-rw-r--r--MdeModulePkg/Library/BrotliCustomDecompressLib/stdio.h9
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c2
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c8
-rw-r--r--MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h4
-rw-r--r--MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c17
-rw-r--r--MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr11
-rw-r--r--MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c46
-rw-r--r--MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c6
-rw-r--r--MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLibNull.c2
-rw-r--r--MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c76
-rw-r--r--MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf4
-rw-r--r--MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c69
-rw-r--r--MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.c2
-rw-r--r--MdeModulePkg/Library/FileExplorerLib/FileExplorer.c6
-rw-r--r--MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf1
-rw-r--r--MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.c4
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/MmCorePerformanceLib.c1306
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c1403
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf31
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h186
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.c208
-rw-r--r--MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf55
-rw-r--r--MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c499
-rw-r--r--MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf5
-rw-r--r--MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.c529
-rw-r--r--MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.h56
-rw-r--r--MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.c55
-rw-r--r--MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.inf48
-rw-r--r--MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.uni20
-rw-r--r--MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.c85
-rw-r--r--MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.inf32
-rw-r--r--MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.c3
-rw-r--r--MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf4
-rw-r--r--MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c127
-rw-r--r--MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c243
-rw-r--r--MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c160
-rw-r--r--MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c6
-rw-r--r--MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h4
-rw-r--r--MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf2
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h10
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c9
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h4
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c251
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.c57
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf8
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.c349
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.h43
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.c138
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.inf53
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c630
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.c152
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.inf47
-rw-r--r--MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.uni15
-rw-r--r--MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c10
-rw-r--r--MdeModulePkg/MdeModulePkg.ci.yaml2
-rw-r--r--MdeModulePkg/MdeModulePkg.dec78
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc31
-rw-r--r--MdeModulePkg/MdeModulePkg.uni6
-rw-r--r--MdeModulePkg/Test/MdeModulePkgHostTest.dsc7
-rw-r--r--MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockHiiLib.h356
-rw-r--r--MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockVariablePolicyHelperLib.h81
-rw-r--r--MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.cpp49
-rw-r--r--MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.inf34
-rw-r--r--MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.cpp14
-rw-r--r--MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.inf33
-rw-r--r--MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h6
-rw-r--r--MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf1
-rw-r--r--MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c239
-rw-r--r--MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c2
-rw-r--r--MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf3
-rw-r--r--MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c21
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c317
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h134
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf14
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.uni11
-rw-r--r--MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c308
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c300
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h19
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf6
-rw-r--r--MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.uni4
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c6
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h7
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c18
-rw-r--r--MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c29
-rw-r--r--MdeModulePkg/Universal/DebugServicePei/DebugServicePei.c2
-rw-r--r--MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c25
-rw-r--r--MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c10
-rw-r--r--MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c9
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c31
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h4
-rw-r--r--MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c8
-rw-r--r--MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.c8
-rw-r--r--MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c2
-rw-r--r--MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c6
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c13
-rw-r--r--MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c4
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c172
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Database.c185
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf1
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Image.c117
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/String.c2
-rw-r--r--MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSample.c2
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c10
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.uni8
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h2
-rw-r--r--MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf6
-rw-r--r--MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.h1
m---------MdeModulePkg/Universal/RegularExpressionDxe/oniguruma0
-rw-r--r--MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.c2
-rw-r--r--MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.c15
-rw-r--r--MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c6
-rw-r--r--MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.c4
-rw-r--r--MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.c27
-rw-r--r--MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf1
-rw-r--r--MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c2
-rw-r--r--MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c4
-rw-r--r--MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h14
-rw-r--r--MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c27
-rw-r--r--MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf4
-rw-r--r--MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c17
-rw-r--r--MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c69
-rw-r--r--MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h1
-rw-r--r--MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf8
-rw-r--r--MdeModulePkg/Universal/Variable/Pei/Variable.c1
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h14
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c2
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c4
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf2
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c293
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf4
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c29
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf1
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c6
264 files changed, 13495 insertions, 7769 deletions
diff --git a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
index d6fb928..a5b092d 100644
--- a/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
+++ b/MdeModulePkg/Application/CapsuleApp/CapsuleApp.c
@@ -1029,6 +1029,7 @@ UefiMain (
Status = gRT->UpdateCapsule (CapsuleHeaderArray, CapsuleNum, (UINTN)BlockDescriptors);
if (Status != EFI_SUCCESS) {
Print (L"CapsuleApp: failed to update capsule - %r\n", Status);
+ goto Done;
}
}
diff --git a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c
index 69baf1c..68c2e35 100644
--- a/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c
+++ b/MdeModulePkg/Application/SmiHandlerProfileInfo/SmiHandlerProfileInfo.c
@@ -667,7 +667,7 @@ SmiHandlerProfileInfoEntrypoint (
//
// Dump all image
//
- Print (L"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
+ Print (L"<?xml version=\"1.0\" encoding=\"utf-16\"?>\n");
Print (L"<SmiHandlerProfile>\n");
Print (L"<ImageDatabase>\n");
Print (L" <!-- SMM image loaded -->\n");
diff --git a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c
index 8bc7883..24f9f1e 100644
--- a/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c
+++ b/MdeModulePkg/Application/UiApp/FrontPageCustomizedUiSupport.c
@@ -392,6 +392,8 @@ UiCreateLanguageMenu (
OptionsOpCodeHandle,
NULL
);
+
+ HiiFreeOpCodeHandle (OptionsOpCodeHandle);
}
/**
@@ -450,7 +452,7 @@ UiCreateResetMenu (
StartOpCodeHandle,
FRONT_PAGE_KEY_RESET,
STRING_TOKEN (STR_RESET_STRING),
- STRING_TOKEN (STR_RESET_STRING),
+ STRING_TOKEN (STR_RESET_STRING_HELP),
EFI_IFR_FLAG_CALLBACK,
0
);
diff --git a/MdeModulePkg/Application/UiApp/FrontPageStrings.uni b/MdeModulePkg/Application/UiApp/FrontPageStrings.uni
index a0ab9ab..bd6e377 100644
--- a/MdeModulePkg/Application/UiApp/FrontPageStrings.uni
+++ b/MdeModulePkg/Application/UiApp/FrontPageStrings.uni
@@ -51,9 +51,9 @@
#string STR_EMPTY_STRING #language en-US ""
#language fr-FR ""
#string STR_RESET_STRING #language en-US "Reset"
- #language fr-FR "Reset"
-#string STR_RESET_STRING_HELP #language en-US "Reset the current setting."
- #language fr-FR "Reset the current setting."
+ #language fr-FR "Réinitialiser"
+#string STR_RESET_STRING_HELP #language en-US "Cold reset (reboots the computer)."
+ #language fr-FR "Réinitialisation à froid (redémarre l'ordinateur)."
#string STR_CUSTOMIZE_BANNER_LINE4_LEFT #language en-US ""
#language fr-FR ""
#string STR_CUSTOMIZE_BANNER_LINE4_RIGHT #language en-US ""
diff --git a/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiPassThru.c b/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiPassThru.c
index 7bd0466..a77ecfc 100644
--- a/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiPassThru.c
+++ b/MdeModulePkg/Bus/Ata/AhciPei/AhciPeiPassThru.c
@@ -384,6 +384,10 @@ Exit:
If PortMultiplierPort is the port multiplier port number of the last ATA device
on the port of the ATA controller, then EFI_NOT_FOUND is returned.
+ When port multiplier is not connected to the Port, GetNextDevice() may either return
+ EFI_SUCCESS and set PortMultiplierPort to 0xFFFF or return EFI_NOT_FOUND (in which case the
+ PortMultiplierPort value is undefined).
+
@param[in] This The PPI instance pointer.
@param[in] Port The port number present on the ATA controller.
@param[in,out] PortMultiplierPort On input, a pointer to the port multiplier
diff --git a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c
index f39c909..986b3e2 100644
--- a/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c
+++ b/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c
@@ -1541,6 +1541,10 @@ Exit:
If PortMultiplierPort is the port multiplier port number of the last ATA device on the port of
the ATA controller, then EFI_NOT_FOUND is returned.
+ When port multiplier is not connected to the Port, GetNextDevice() may either return
+ EFI_SUCCESS and set PortMultiplierPort to 0xFFFF or return EFI_NOT_FOUND (in which case the
+ PortMultiplierPort value is undefined).
+
@param[in] This A pointer to the EFI_ATA_PASS_THRU_PROTOCOL instance.
@param[in] Port The port number present on the ATA controller.
@param[in, out] PortMultiplierPort On input, a pointer to the port multiplier port number of an
diff --git a/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.c b/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.c
index 3f5462c..8e21fd1 100644
--- a/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.c
+++ b/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.c
@@ -6,6 +6,7 @@ This PPI can be consumed by PEIM which produce gEfiPeiDeviceRecoveryModulePpiGui
for Atapi CD ROM device.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -1198,7 +1199,7 @@ CheckErrorStatus (
}
/**
- Idendify Atapi devices.
+ Identify Atapi devices.
@param[in] AtapiBlkIoDev A pointer to atapi block IO device.
@param[in] DevicePosition An integer to signify device position.
diff --git a/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.h b/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.h
index abc1dc6..4cff117 100644
--- a/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.h
+++ b/MdeModulePkg/Bus/Pci/IdeBusPei/AtapiPeim.h
@@ -2,6 +2,7 @@
Private Include file for IdeBus PEIM.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -524,7 +525,7 @@ CheckErrorStatus (
);
/**
- Idendify Atapi devices.
+ Identify Atapi devices.
@param[in] AtapiBlkIoDev A pointer to atapi block IO device.
@param[in] DevicePosition An integer to signify device position.
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index e31c38d..4daf517 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -1111,6 +1111,8 @@ NonCoherentPciIoAllocateBuffer (
NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
VOID *AllocAddress;
+ MemType = EFI_MEMORY_XP;
+
if (HostAddress == NULL) {
return EFI_INVALID_PARAMETER;
}
@@ -1152,9 +1154,9 @@ NonCoherentPciIoAllocateBuffer (
// Use write combining if it was requested, or if it is the only
// type supported by the region.
//
- MemType = EFI_MEMORY_WC;
+ MemType |= EFI_MEMORY_WC;
} else {
- MemType = EFI_MEMORY_UC;
+ MemType |= EFI_MEMORY_UC;
}
Alloc = AllocatePool (sizeof *Alloc);
@@ -1172,6 +1174,34 @@ NonCoherentPciIoAllocateBuffer (
//
InsertHeadList (&Dev->UncachedAllocationList, &Alloc->List);
+ //
+ // Ensure that EFI_MEMORY_XP is in the capability set
+ //
+ if ((GcdDescriptor.Capabilities & EFI_MEMORY_XP) != EFI_MEMORY_XP) {
+ Status = gDS->SetMemorySpaceCapabilities (
+ (PHYSICAL_ADDRESS)(UINTN)AllocAddress,
+ EFI_PAGES_TO_SIZE (Pages),
+ GcdDescriptor.Capabilities | EFI_MEMORY_XP
+ );
+
+ // if we were to fail setting the capability, this would indicate an internal failure of the GCD code. We should
+ // assert here to let a platform know something went crazy, but for a release build we can let the allocation occur
+ // without the EFI_MEMORY_XP bit set, as that was the existing behavior
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a failed to set EFI_MEMORY_XP capability on 0x%llx for length 0x%llx. Attempting to allocate without XP set.\n",
+ __func__,
+ AllocAddress,
+ EFI_PAGES_TO_SIZE (Pages)
+ ));
+
+ ASSERT_EFI_ERROR (Status);
+
+ MemType &= ~EFI_MEMORY_XP;
+ }
+ }
+
Status = gDS->SetMemorySpaceAttributes (
(EFI_PHYSICAL_ADDRESS)(UINTN)AllocAddress,
EFI_PAGES_TO_SIZE (Pages),
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
index 069da12..c8d8be3 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.c
@@ -3,6 +3,7 @@
NVM Express specification.
Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -182,6 +183,26 @@ EnumerateNvmeDevNamespace (
InitializeListHead (&Device->AsyncQueue);
//
+ // Create Media Sanitize Protocol instance
+ //
+ Device->MediaSanitize.Revision = MEDIA_SANITIZE_PROTOCOL_REVISION;
+ Device->MediaSanitize.Media = &Device->Media;
+ Device->MediaSanitize.MediaClear = NvmExpressMediaClear;
+ Device->MediaSanitize.MediaPurge = NvmExpressMediaPurge;
+ Device->MediaSanitize.MediaFormat = NvmExpressMediaFormat;
+
+ ASSERT (
+ sizeof (Device->MediaSanitize.SanitizeCapabilities) ==
+ sizeof (Device->Controller->ControllerData->Sanicap)
+ );
+
+ CopyMem (
+ &(Device->MediaSanitize.SanitizeCapabilities),
+ &(Device->Controller->ControllerData->Sanicap),
+ sizeof (Device->MediaSanitize.SanitizeCapabilities)
+ );
+
+ //
// Create StorageSecurityProtocol Instance
//
Device->StorageSecurity.ReceiveData = NvmeStorageSecurityReceiveData;
@@ -241,6 +262,8 @@ EnumerateNvmeDevNamespace (
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
+ &gMediaSanitizeProtocolGuid,
+ &Device->MediaSanitize,
NULL
);
@@ -269,6 +292,8 @@ EnumerateNvmeDevNamespace (
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
+ &gMediaSanitizeProtocolGuid,
+ &Device->MediaSanitize,
NULL
);
goto Exit;
@@ -468,6 +493,8 @@ UnregisterNvmeNamespace (
&Device->BlockIo2,
&gEfiDiskInfoProtocolGuid,
&Device->DiskInfo,
+ &gMediaSanitizeProtocolGuid,
+ &Device->MediaSanitize,
NULL
);
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
index 4c26b2e..11207af 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpress.h
@@ -4,6 +4,7 @@
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -29,6 +30,7 @@
#include <Protocol/DriverSupportedEfiVersion.h>
#include <Protocol/StorageSecurityCommand.h>
#include <Protocol/ResetNotification.h>
+#include <Protocol/MediaSanitize.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
@@ -41,12 +43,15 @@
#include <Library/UefiDriverEntryPoint.h>
#include <Library/ReportStatusCodeLib.h>
+#include <Guid/NVMeEventGroup.h>
+
typedef struct _NVME_CONTROLLER_PRIVATE_DATA NVME_CONTROLLER_PRIVATE_DATA;
typedef struct _NVME_DEVICE_PRIVATE_DATA NVME_DEVICE_PRIVATE_DATA;
#include "NvmExpressBlockIo.h"
#include "NvmExpressDiskInfo.h"
#include "NvmExpressHci.h"
+#include "NvmExpressMediaSanitize.h"
extern EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gNvmExpressComponentName;
@@ -75,6 +80,30 @@ extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiV
#define NVME_MAX_QUEUES 3 // Number of queues supported by the driver
+//
+// FormatNVM Admin Command LBA Format (LBAF) Mask
+//
+#define NVME_LBA_FORMATNVM_LBAF_MASK 0xF
+
+//
+// NVMe Completion Queue Entry Bits, Fields, Masks
+//
+#define NVME_CQE_STATUS_FIELD_MASK 0xFFFF0000
+#define NVME_CQE_STATUS_FIELD_OFFSET 16
+#define NVME_CQE_STATUS_FIELD_SCT_MASK 0x0E00
+#define NVME_CQE_STATUS_FIELD_SCT_OFFSET 0x9
+#define NVME_CQE_STATUS_FIELD_SC_MASK 0x1FE
+#define NVME_CQE_STATUS_FIELD_SC_OFFSET 0x01
+#define NVME_CQE_SCT_GENERIC_CMD_STATUS 0x0
+#define NVME_CQE_SCT_CMD_SPECIFIC_STATUS 0x1
+#define NVME_CQE_SCT_MEDIA_DATA_INTEGRITY_ERRORS_STATUS 0x2
+#define NVME_CQE_SCT_PATH_RELATED_STATUS 0x3
+#define NVME_CQE_SC_SUCCESSFUL_COMPLETION 0x00
+#define NVME_CQE_SC_INVALID_CMD_OPCODE 0x01
+#define NVME_CQE_SC_INVALID_FIELD_IN_CMD 0x02
+
+#define NVME_ALL_NAMESPACES 0xFFFFFFFF
+
#define NVME_CONTROLLER_ID 0
//
@@ -200,6 +229,8 @@ struct _NVME_DEVICE_PRIVATE_DATA {
EFI_DISK_INFO_PROTOCOL DiskInfo;
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity;
+ MEDIA_SANITIZE_PROTOCOL MediaSanitize;
+
LIST_ENTRY AsyncQueue;
EFI_LBA NumBlocks;
@@ -241,6 +272,13 @@ struct _NVME_DEVICE_PRIVATE_DATA {
NVME_DEVICE_PRIVATE_DATA_SIGNATURE \
)
+#define NVME_DEVICE_PRIVATE_DATA_FROM_MEDIA_SANITIZE(a) \
+ CR (a, \
+ NVME_DEVICE_PRIVATE_DATA, \
+ MediaSanitize, \
+ NVME_DEVICE_PRIVATE_DATA_SIGNATURE \
+ )
+
//
// Nvme block I/O 2 request.
//
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
index dc1990c..5fd0e46 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
@@ -5,7 +5,7 @@
# NVM Express specification.
#
# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
-#
+# Copyright (c) Microsoft Corporation.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -40,9 +40,16 @@
NvmExpressHci.c
NvmExpressHci.h
NvmExpressPassthru.c
+ NvmExpressMediaSanitize.c
+ NvmExpressMediaSanitize.h
+
+[Guids]
+ gNVMeEnableStartEventGroupGuid
+ gNVMeEnableCompleteEventGroupGuid
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
BaseMemoryLib
@@ -67,6 +74,7 @@
gEfiDiskInfoProtocolGuid ## BY_START
gEfiStorageSecurityCommandProtocolGuid ## BY_START
gEfiDriverSupportedEfiVersionProtocolGuid ## PRODUCES
+ gMediaSanitizeProtocolGuid ## PRODUCES
gEfiResetNotificationProtocolGuid ## CONSUMES
# [Event]
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
index b90c487..e1b0ee6 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressHci.c
@@ -8,6 +8,7 @@
**/
#include "NvmExpress.h"
+#include <Guid/NVMeEventGroup.h>
#define NVME_SHUTDOWN_PROCESS_TIMEOUT 45
@@ -399,6 +400,8 @@ NvmeEnableController (
UINT32 Index;
UINT8 Timeout;
+ EfiEventGroupSignal (&gNVMeEnableStartEventGroupGuid);
+
//
// Enable the controller.
// CC.AMS, CC.MPS and CC.CSS are all set to 0.
@@ -410,7 +413,7 @@ NvmeEnableController (
Status = WriteNvmeControllerConfiguration (Private, &Cc);
if (EFI_ERROR (Status)) {
- return Status;
+ goto Cleanup;
}
//
@@ -432,7 +435,7 @@ NvmeEnableController (
Status = ReadNvmeControllerStatus (Private, &Csts);
if (EFI_ERROR (Status)) {
- return Status;
+ goto Cleanup;
}
if (Csts.Rdy) {
@@ -449,6 +452,9 @@ NvmeEnableController (
}
DEBUG ((DEBUG_INFO, "NVMe controller is enabled with status [%r].\n", Status));
+
+Cleanup:
+ EfiEventGroupSignal (&gNVMeEnableCompleteEventGroupGuid);
return Status;
}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.c
new file mode 100644
index 0000000..dd24c2c
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.c
@@ -0,0 +1,584 @@
+/** @file -- NvmExpressMediaSanitize.c
+ This driver will implement sanitize operations on all NVMe mass storage devices
+ based on NIST purge and clear operations. These operations will then be mapped to
+ one of two NVMe admin commands:
+
+ -Format NVM
+ -Sanitize
+
+ Implementation based off NVMe spec revision 1.4c.
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "NvmExpress.h"
+
+/**
+ Send NVM Express FormatNVM Admin Command
+
+ The Format NVM command is used to low level format the NVM media. This command is used by
+ the host to change the LBA data size and/or metadata size.
+
+ A low level format may destroy all data and metadata associated with all namespaces or only
+ the specific namespace associated with the command (refer to the Format NVM Attributes field
+ in the Identify Controller data structure).
+
+ After the Format NVM command successfully completes, the controller shall not return any user
+ data that was previously contained in an affected namespace.
+
+ @param[in] This Indicates a pointer to the calling context (Block IO Protocol)
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] Ses Secure Erase Setting (SES) value
+ - 000b: No secure erase operation requested
+ - 001b: User Data Erase
+ - 010b: Cryptographic Erase
+ - 011b to 111b: Reserved
+ @param[in] Flbas New LBA size (in terms of LBA Format size Index (bits 3:0) in NamespaceData).
+ If this param is 0 (NULL), then use existing LBA size.
+
+ @retval EFI_SUCCESS The device formatted correctly.
+ @retval EFI_WRITE_PROTECTED The device can not be formatted due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the format.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_INVALID_PARAMETER The format request contains parameters that are not valid.
+
+ **/
+EFI_STATUS
+NvmExpressFormatNvm (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT32 Ses,
+ IN UINT32 Flbas
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ EFI_NVM_EXPRESS_COMMAND Command;
+ EFI_NVM_EXPRESS_COMPLETION Completion;
+ NVME_ADMIN_FORMAT_NVM FormatNvmCdw10;
+ NVME_ADMIN_NAMESPACE_DATA *NewNamespaceData;
+ UINT32 Lbads;
+ UINT32 NewFlbas;
+ UINT32 LbaFmtIdx;
+ EFI_STATUS Status;
+ UINT32 LbaFormat;
+ UINT16 StatusField;
+ UINT16 Sct;
+ UINT16 Sc;
+
+ Status = EFI_NOT_STARTED;
+ LbaFormat = 0;
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+
+ ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
+ ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
+ ZeroMem (&FormatNvmCdw10, sizeof (NVME_ADMIN_FORMAT_NVM));
+
+ NewNamespaceData = NULL;
+ Lbads = 0;
+ NewFlbas = 0;
+ LbaFmtIdx = 0;
+ StatusField = 0;
+ Sct = 0;
+ Sc = 0;
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeCompletion = &Completion;
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;
+ Command.Cdw0.Opcode = NVME_ADMIN_FORMAT_NVM_CMD;
+ Command.Nsid = NamespaceId;
+
+ //
+ // SES (Secure Erase Settings)
+ //
+ FormatNvmCdw10.Ses = Ses;
+
+ //
+ // Change LBA size/format if LbaFormat param != NULL, otherwise keep same LBA format.
+ // Current supported LBA format size in Identify Namespace LBA Format Table, indexed by
+ // FLBAS (bits 3:0).
+ //
+ LbaFormat = (Flbas == 0 ? Device->NamespaceData.Flbas : Flbas);
+ FormatNvmCdw10.Lbaf = LbaFormat & NVME_LBA_FORMATNVM_LBAF_MASK;
+ CopyMem (&CommandPacket.NvmeCmd->Cdw10, &FormatNvmCdw10, sizeof (NVME_ADMIN_FORMAT_NVM));
+
+ //
+ // Send Format NVM command via passthru and wait for completion
+ //
+ // If LBA size changed successfully, then update private data structures and Block IO
+ // and Media protocols to reflect new LBA size.
+ //
+ Status = Device->Controller->Passthru.PassThru (
+ &(Device->Controller->Passthru),
+ NamespaceId,
+ &CommandPacket,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ StatusField = (UINT16)((CommandPacket.NvmeCompletion->DW3 & NVME_CQE_STATUS_FIELD_MASK) >>
+ NVME_CQE_STATUS_FIELD_OFFSET);
+
+ Sc = (StatusField & NVME_CQE_STATUS_FIELD_SC_MASK) >> NVME_CQE_STATUS_FIELD_SC_OFFSET;
+ Sct = (StatusField & NVME_CQE_STATUS_FIELD_SCT_MASK) >> NVME_CQE_STATUS_FIELD_SCT_OFFSET;
+
+ DEBUG ((DEBUG_ERROR, "%a: NVMe FormatNVM admin command failed SCT = 0x%x, SC = 0x%x\n", __func__, Sct, Sc));
+ } else {
+ //
+ // Update Block IO and Media Protocols only if Flbas parameter was not NULL.
+ // Call Identify Namespace again and update all protocols fields and local
+ // cached copies of fields related to block size.
+ //
+ if (Flbas != 0) {
+ NewNamespaceData = AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ if (NewNamespaceData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = NvmeIdentifyNamespace (
+ Device->Controller,
+ NamespaceId,
+ (VOID *)NewNamespaceData
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Update all fields related to LBA size, allocation, and alignment
+ //
+ NewFlbas = NewNamespaceData->Flbas;
+ LbaFmtIdx = NewFlbas & NVME_LBA_FORMATNVM_LBAF_MASK;
+ Lbads = NewNamespaceData->LbaFormat[LbaFmtIdx].Lbads;
+ Device->Media.BlockSize = (UINT32)1 << Lbads;
+ Device->Media.LastBlock = NewNamespaceData->Nsze - 1;
+
+ CopyMem (&Device->NamespaceData, NewNamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ }
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Send NVM Express Sanitize Admin Command
+
+ The Sanitize command is used to start a sanitize operation or to recover from a previously
+ failed sanitize operation. The sanitize operation types that may be supported are Block
+ Erase, Crypto Erase, and Overwrite.
+
+ All sanitize operations are processed in the background (i.e., completion of the Sanitize
+ command does not indicate completion of the sanitize operation).
+
+ @param[in] This Indicates a pointer to the calling context (Block IO Protocol)
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] SanitizeAction Sanitize action
+ @param[in] NoDeallocAfterSanitize No deallocate after sanitize option
+ @param[in] OverwritePattern Pattern to overwrite old user data
+
+ @retval EFI_SUCCESS The media was sanitized successfully on the device.
+ @retval EFI_WRITE_PROTECTED The device can not be sanitized due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the sanitize.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The sanitize request contains parameters that are not valid.
+
+ **/
+EFI_STATUS
+NvmExpressSanitize (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT32 SanitizeAction,
+ IN UINT32 NoDeallocAfterSanitize,
+ IN UINT32 OverwritePattern
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ EFI_NVM_EXPRESS_COMMAND Command;
+ EFI_NVM_EXPRESS_COMPLETION Completion;
+ NVME_ADMIN_SANITIZE SanitizeCdw10Cdw11;
+ EFI_STATUS Status;
+ UINT16 StatusField;
+ UINT16 Sct;
+ UINT16 Sc;
+ UINT32 FnvmSes;
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+
+ ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
+ ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
+ ZeroMem (&SanitizeCdw10Cdw11, sizeof (NVME_ADMIN_SANITIZE));
+
+ StatusField = 0;
+ Sct = 0;
+ Sc = 0;
+ FnvmSes = 0;
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeCompletion = &Completion;
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;
+ Command.Cdw0.Opcode = NVME_ADMIN_SANITIZE_CMD;
+ Command.Nsid = NamespaceId;
+
+ SanitizeCdw10Cdw11.Nodas = NoDeallocAfterSanitize;
+ SanitizeCdw10Cdw11.Sanact = SanitizeAction;
+ SanitizeCdw10Cdw11.Ovrpat = OverwritePattern;
+ CopyMem (&CommandPacket.NvmeCmd->Cdw10, &SanitizeCdw10Cdw11, sizeof (NVME_ADMIN_SANITIZE));
+
+ //
+ // Send Format NVM command via passthru and wait for completion
+ //
+ Status = Device->Controller->Passthru.PassThru (
+ &(Device->Controller->Passthru),
+ NamespaceId,
+ &CommandPacket,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ StatusField = (UINT16)((CommandPacket.NvmeCompletion->DW3 & NVME_CQE_STATUS_FIELD_MASK) >>
+ NVME_CQE_STATUS_FIELD_OFFSET);
+
+ Sc = (StatusField & NVME_CQE_STATUS_FIELD_SC_MASK) >> NVME_CQE_STATUS_FIELD_SC_OFFSET;
+ Sct = (StatusField & NVME_CQE_STATUS_FIELD_SCT_MASK) >> NVME_CQE_STATUS_FIELD_SCT_OFFSET;
+
+ DEBUG ((DEBUG_ERROR, "%a: NVMe Sanitize admin command failed SCT = 0x%x, SC = 0x%x\n", __func__, Sct, Sc));
+
+ //
+ // Check for an error status code of "Invalid Command Opcode" in case
+ // the NVM Express controller does not support Sanitize. If the NVM
+ // Exress Controller does not support Sanitize, then send a Format NVM
+ // admin command instead to perform the Purge operation.
+ //
+ if ((Sct == NVME_CQE_SCT_GENERIC_CMD_STATUS) &&
+ (Sc == NVME_CQE_SC_INVALID_CMD_OPCODE))
+ {
+ switch (SanitizeCdw10Cdw11.Sanact) {
+ case SANITIZE_ACTION_BLOCK_ERASE:
+ FnvmSes = SES_USER_DATA_ERASE; // User Data Erase (LBAs indeterminate after)
+ break;
+ case SANITIZE_ACTION_CRYPTO_ERASE:
+ FnvmSes = SES_CRYPTO_ERASE; // Crypto Erase
+ break;
+ case SANITIZE_ACTION_OVERWRITE:
+ case SANITIZE_ACTION_EXIT_FAILURE_MODE:
+ default:
+ //
+ // Cannot perform an equivalent FormatNVM action/operation
+ //
+ FnvmSes = SES_NO_SECURE_ERASE;
+ break;
+ }
+
+ if ((FnvmSes == SES_USER_DATA_ERASE) || (FnvmSes == SES_CRYPTO_ERASE)) {
+ Status = NvmExpressFormatNvm (
+ This,
+ NVME_ALL_NAMESPACES,
+ FnvmSes,
+ 0 // Pass in NULL so existing LBA size is used in Format NVM
+ );
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Clear Media utilizes transport native WRITE commands to write a fixed pattern
+ of non-sensitive data to the media.
+
+ NOTE: The caller shall send buffer of one sector/LBA size with overwrite data.
+ NOTE: This operation is a blocking call.
+ NOTE: This function must be called from TPL_APPLICATION or TPL_CALLBACK.
+
+ Functions are defined to erase and purge data at a block level from mass
+ storage devices as well as to manage such devices in the EFI boot services
+ environment.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the write request is for.
+ @param[in] PassCount The number of passes to write over media.
+ @param[in] SectorOwBuffer A pointer to the overwrite buffer.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressMediaClear (
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 PassCount,
+ IN VOID *SectorOwBuffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_BLOCK_IO_MEDIA *Media;
+ EFI_LBA SectorOffset;
+ UINT32 TotalPassCount;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_MEDIA_SANITIZE (This);
+ Media = &Device->Media;
+ SectorOffset = 0;
+
+ if ((MediaId != Media->MediaId) || (!Media->MediaPresent)) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ //
+ // If an invalid buffer or buffer size is sent, the Media Clear operation
+ // cannot be performed as it requires a native WRITE command. The overwrite
+ // buffer must have granularity of a namespace block size.
+ //
+ if (SectorOwBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Per NIST 800-88r1, one or more pass of writes may be alteratively used.
+ //
+ for (TotalPassCount = 0; TotalPassCount < PassCount; TotalPassCount++) {
+ for (SectorOffset = 0; SectorOffset < Media->LastBlock; SectorOffset++ ) {
+ Status = Device->BlockIo.WriteBlocks (
+ &Device->BlockIo,
+ MediaId,
+ SectorOffset, // Sector/LBA offset (increment each pass)
+ 1, // Write one sector per write
+ SectorOwBuffer // overwrite buffer
+ );
+ }
+
+ //
+ // Reset SectorOffset back to zero if another pass on namespace is needed
+ //
+ SectorOffset = 0;
+ }
+
+ return Status;
+}
+
+/**
+ Purge Media utilizes transport native Sanitize operations. Sanitize specific
+ purge actions include: overwrite, block erase, or crypto erase.
+
+ Functions are defined to erase and purge data at a block level from mass
+ storage devices as well as to manage such devices in the EFI boot services
+ environment. Sanitization refers to a process that renders access to target
+ data on the media infeasible for a given level of effort.
+
+ NOTE: This operation is a blocking call.
+ NOTE: This function must be called from TPL_APPLICATION or TPL_CALLBACK.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the write request is for.
+ @param[in] PurgeAction The purage action (overwrite, crypto erase, block erase).
+ @param[in] OverwritePattern 32-bit pattern to overwrite on media (for overwrite).
+
+ @retval EFI_SUCCESS The media was purged successfully on the device.
+ @retval EFI_WRITE_PROTECTED The device can not be purged due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the purge.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The purge request contains parameters that are not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressMediaPurge (
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 PurgeAction,
+ IN UINT32 OverwritePattern
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_BLOCK_IO_MEDIA *Media;
+ NVME_SANICAP SaniCap;
+ UINT32 SanitizeAction;
+ UINT32 NoDeallocate;
+ UINT32 NamespaceId;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_MEDIA_SANITIZE (This);
+ NamespaceId = Device->NamespaceId;
+ Media = &Device->Media;
+ SaniCap = Device->Controller->ControllerData->Sanicap;
+ NoDeallocate = 0;
+
+ if ((MediaId != Media->MediaId) || (!Media->MediaPresent)) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ //
+ // Purge action will directly map to sanitize action. If no valid purge
+ // action is selected, then default to no action and let the NVMe SSD handle
+ // the no-op sanitize action (as there may be other contingencies).
+ //
+ if (((PurgeAction & PURGE_ACTION_OVERWRITE) == PURGE_ACTION_OVERWRITE) && (SaniCap.Ows)) {
+ SanitizeAction = SANITIZE_ACTION_OVERWRITE;
+ } else if (((PurgeAction & PURGE_ACTION_BLOCK_ERASE) == PURGE_ACTION_BLOCK_ERASE) && (SaniCap.Bes)) {
+ SanitizeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ } else if (((PurgeAction & PURGE_ACTION_CRYPTO_ERASE) == PURGE_ACTION_CRYPTO_ERASE) && (SaniCap.Ces)) {
+ SanitizeAction = SANITIZE_ACTION_CRYPTO_ERASE;
+ } else {
+ SanitizeAction = SANITIZE_ACTION_NO_ACTION;
+ }
+
+ if ((PurgeAction & PURGE_ACTION_NO_DEALLOCATE) == PURGE_ACTION_NO_DEALLOCATE) {
+ NoDeallocate = NVME_NO_DEALLOCATE_AFTER_SANITZE;
+ }
+
+ //
+ // Call NVM Express Admin command Sanitize (blocking call).
+ //
+ Status = NvmExpressSanitize (
+ &Device->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocate,
+ OverwritePattern
+ );
+
+ return Status;
+}
+
+/**
+ Format Media utilizes native format operations to modify sector/LBA size.
+ Secure erase actions are used to define how latent user data is erased.
+
+ NOTE: This function must be called from TPL_APPLICATION or TPL_CALLBACK.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the clear request is for.
+ @param[in] LbaSize Size of LBA (in terms of power of two: 2^n).
+ @param[in] SecureEraseAction Secure erase action, if any, to apply to format.
+ - 000b: No secure erase operation requested
+ - 001b: User Data Erase
+ - 010b: Cryptographic Erase
+ - 011b to 111b: Reserved
+
+ @retval EFI_SUCCESS The media format request comopleted successfully on the device.
+ @retval EFI_WRITE_PROTECTED The device can't be formatted due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the format operation.
+ @retval EFI_INVALID_PARAMETER The format request contains parameters that are not valid.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmExpressMediaFormat (
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 LbaSize,
+ IN UINT32 SecureEraseAction
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINT32 NamespaceId;
+ UINT32 SecureEraseSettings;
+ UINT32 FlbaIndex;
+ BOOLEAN LbaSizeIsSupported;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_MEDIA_SANITIZE (This);
+ NamespaceId = Device->NamespaceId;
+ Media = &Device->Media;
+ SecureEraseSettings = FORMAT_SES_NO_SECURE_ERASE_REQUESTED;
+ FlbaIndex = 0;
+
+ if ((MediaId != Media->MediaId) || (!Media->MediaPresent)) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ //
+ // Convert secure erase action to NVMe secure erase setting
+ //
+ switch (SecureEraseAction) {
+ case FORMAT_SES_USER_DATA_ERASE:
+ SecureEraseSettings = SES_USER_DATA_ERASE;
+ break;
+ case FORMAT_SES_CRYPTOGRAPHIC_ERASE:
+ SecureEraseSettings = SES_CRYPTO_ERASE;
+ break;
+ case FORMAT_SES_NO_SECURE_ERASE_REQUESTED:
+ default:
+ //
+ // Cannot perform an equivalent FormatNVM action/operation
+ //
+ SecureEraseSettings = SES_NO_SECURE_ERASE;
+ break;
+ }
+
+ //
+ // The requested LBA size must be supported by the NVMe SSD as defined in Identify
+ // Namespace structure.
+ //
+ // Current supported LBA format sizes is in Identify Namespace LBA Format Table,
+ // indexed by FLBAS (bits 3:0). Loop through all supported LBADF sizes and check
+ // to see if requested LBA size is supported. If yes, send FormatNVM command.
+ //
+ LbaSizeIsSupported = FALSE;
+ for (FlbaIndex = 0; FlbaIndex < Device->NamespaceData.Nlbaf; FlbaIndex++) {
+ if (Device->NamespaceData.LbaFormat[FlbaIndex].Lbads == LbaSize) {
+ LbaSizeIsSupported = TRUE;
+ break;
+ }
+ }
+
+ if (LbaSizeIsSupported) {
+ Status = NvmExpressFormatNvm (
+ &Device->BlockIo,
+ NamespaceId,
+ SecureEraseSettings,
+ FlbaIndex
+ );
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.h b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.h
new file mode 100644
index 0000000..197b923
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressMediaSanitize.h
@@ -0,0 +1,191 @@
+/** @file
+ Header file for MEDIA_SANITIZE_PROTOCOL interface.
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef NVME_MEDIA_SANITIZE_H_
+#define NVME_MEDIA_SANITIZE_H_
+
+#define NVME_NO_DEALLOCATE_AFTER_SANITZE 0x1
+
+/**
+ Send NVM Express FormatNVM Admin Command
+
+ The Format NVM command is used to low level format the NVM media. This command is used by
+ the host to change the LBA data size and/or metadata size.
+
+ A low level format may destroy all data and metadata associated with all namespaces or only
+ the specific namespace associated with the command (refer to the Format NVM Attributes field
+ in the Identify Controller data structure).
+
+ After the Format NVM command successfully completes, the controller shall not return any user
+ data that was previously contained in an affected namespace.
+
+ @param[in] This Indicates a pointer to the calling context (Block IO Protocol)
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] Ses Secure Erase Setting (SES) value
+ - 000b: No secure erase operation requested
+ - 001b: User Data Erase
+ - 010b: Cryptographic Erase
+ - 011b to 111b: Reserved
+ @param[in] Flbas New LBA size (in terms of LBA Format size Index (bits 3:0) in NamespaceData).
+ If this param is 0 (NULL), then use existing LBA size.
+
+ @retval EFI_SUCCESS The device formatted correctly.
+ @retval EFI_WRITE_PROTECTED The device can not be formatted due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the format.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_INVALID_PARAMETER The format request contains parameters that are not valid.
+
+**/
+EFI_STATUS
+NvmExpressFormatNvm (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT32 Ses,
+ IN UINT32 Flbas
+ );
+
+/**
+ Send NVM Express Sanitize Admin Command
+
+ The Sanitize command is used to start a sanitize operation or to recover from a previously
+ failed sanitize operation. The sanitize operation types that may be supported are Block
+ Erase, Crypto Erase, and Overwrite.
+
+ All sanitize operations are processed in the background (i.e., completion of the Sanitize
+ command does not indicate completion of the sanitize operation).
+
+ @param[in] This Indicates a pointer to the calling context (Block IO Protocol)
+ @param[in] NamespaceId The NVM Express namespace ID for which a device path node is to be
+ allocated and built. Caller must set the NamespaceId to zero if the
+ device path node will contain a valid UUID.
+ @param[in] SanitizeAction Sanitize action
+ @param[in] NoDeallocAfterSanitize No deallocate after sanitize option
+ @param[in] OverwritePattern Pattern to overwrite old user data
+
+ @retval EFI_SUCCESS The media was sanitized successfully on the device.
+ @retval EFI_WRITE_PROTECTED The device can not be sanitized due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the sanitize.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The sanitize request contains parameters that are not valid.
+
+**/
+EFI_STATUS
+NvmExpressSanitize (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN UINT32 SanitizeAction,
+ IN UINT32 NoDeallocAfterSanitize,
+ IN UINT32 OverwritePattern
+ );
+
+/**
+ Clear Media utilizes transport native WRITE commands to write a fixed pattern
+ of non-sensitive data to the media.
+
+ NOTE: The caller shall send buffer of one sector/LBA size with overwrite data.
+ NOTE: This operation is a blocking call.
+ NOTE: This function must be called from TPL_APPLICATION or TPL_CALLBACK.
+
+ Functions are defined to erase and purge data at a block level from mass
+ storage devices as well as to manage such devices in the EFI boot services
+ environment.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the write request is for.
+ @param[in] PassCount The number of passes to write over media.
+ @param[in] SectorOwBuffer A pointer to the overwrite buffer.
+
+ @retval EFI_SUCCESS The data was written correctly to the device.
+ @retval EFI_WRITE_PROTECTED The device can not be written to.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the write.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
+ @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+ or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressMediaClear (
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 PassCount,
+ IN VOID *SectorOwBuffer
+ );
+
+/**
+ Purge Media utilizes transport native Sanitize operations. Sanitize specific
+ purge actions include: overwrite, block erase, or crypto erase.
+
+ Functions are defined to erase and purge data at a block level from mass
+ storage devices as well as to manage such devices in the EFI boot services
+ environment. Sanitization refers to a process that renders access to target
+ data on the media infeasible for a given level of effort.
+
+ NOTE: This operation is a blocking call.
+ NOTE: This function must be called from TPL_APPLICATION or TPL_CALLBACK.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the write request is for.
+ @param[in] PurgeAction The purage action (overwrite, crypto erase, block erase).
+ @param[in] OverwritePattern 32-bit pattern to overwrite on media (for overwrite).
+
+ @retval EFI_SUCCESS The media was purged successfully on the device.
+ @retval EFI_WRITE_PROTECTED The device can not be purged due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while performing the purge.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHNAGED The MediaId does not match the current device.
+ @retval EFI_INVALID_PARAMETER The purge request contains parameters that are not valid.
+
+**/
+EFI_STATUS
+EFIAPI
+NvmExpressMediaPurge (
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 PurgeAction,
+ IN UINT32 OverwritePattern
+ );
+
+/**
+ Format Media utilizes native format operations to modify sector/LBA size.
+ Secure erase actions are used to define how latent user data is erased.
+
+ NOTE: This function must be called from TPL_APPLICATION or TPL_CALLBACK.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the clear request is for.
+ @param[in] LbaSize Size of LBA (in terms of power of two: 2^n).
+ @param[in] SecureEraseAction Secure erase action, if any, to apply to format.
+ - 000b: No secure erase operation requested
+ - 001b: User Data Erase
+ - 010b: Cryptographic Erase
+ - 011b to 111b: Reserved
+
+ @retval EFI_SUCCESS The media format request completed successfully on the device.
+ @retval EFI_WRITE_PROTECTED The device can't be formatted due to write protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the format operation.
+ @retval EFI_INVALID_PARAMETER The format request contains parameters that are not valid.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmExpressMediaFormat (
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 LbaSize,
+ IN UINT32 SecureEraseAction
+ );
+
+#endif
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
index 2ff2cb0..f818e48 100644
--- a/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressPassthru.c
@@ -824,6 +824,8 @@ NvmExpressPassThru (
//
CopyMem (Packet->NvmeCompletion, (VOID *)Cq, sizeof (EFI_NVM_EXPRESS_COMPLETION));
} else {
+ ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE), (EFI_IO_BUS_SCSI | EFI_IOB_EC_INTERFACE_ERROR));
+
//
// Timeout occurs for an NVMe command. Reset the controller to abort the
// outstanding commands.
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c b/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c
new file mode 100644
index 0000000..b872858
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c
@@ -0,0 +1,1128 @@
+/** @file -- MediaSanitizeUnitTest.c
+ Placeholder/framework for developing a Media Sanitize unit test package.
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/NvmExpressPassthru.h>
+#include <Protocol/MediaSanitize.h>
+
+#include "../NvmExpress.h"
+#include "../NvmExpressBlockIo.h"
+#include "../NvmExpressMediaSanitize.h"
+#include "../NvmExpressHci.h"
+
+/**
+ Helper function for Nvme pass thru.
+
+ @param[in] This Private Data.
+ @param[in] NamespaceId Name Space Id.
+ @param[in,out] Packet Transfer Buffer.
+ @param[in] Event Event handle.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeDeviceUnitTestPassthru (
+ IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This,
+ IN UINT32 NamespaceId,
+ IN OUT EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ //
+ // Parse command packet for unit testing
+ //
+ EFI_NVM_EXPRESS_COMMAND *Command;
+ EFI_NVM_EXPRESS_COMPLETION *Completion;
+ NVME_CQ *Cqe;
+ NVME_ADMIN_FORMAT_NVM FormatNvmCdw10;
+ NVME_ADMIN_SANITIZE SanitizeCdw1011;
+
+ ASSERT (This);
+ ASSERT (Packet);
+
+ Command = Packet->NvmeCmd;
+ Completion = Packet->NvmeCompletion;
+ Cqe = (NVME_CQ *)Completion;
+
+ ZeroMem (&FormatNvmCdw10, sizeof (NVME_ADMIN_FORMAT_NVM));
+ ZeroMem (&SanitizeCdw1011, sizeof (NVME_ADMIN_SANITIZE));
+
+ switch (Command->Cdw0.Opcode) {
+ case NVME_ADMIN_FORMAT_NVM_CMD:
+ UT_LOG_VERBOSE ("%a: Opcode = NVME_ADMIN_FORMAT_NVM_CMD\n", __func__);
+
+ CopyMem (&FormatNvmCdw10, &Command->Cdw10, sizeof (NVME_ADMIN_FORMAT_NVM));
+
+ //
+ // FormatNVM Check 1: Validate SES parameter
+ //
+ if (FormatNvmCdw10.Ses > 0x2) {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // FormatNVM Check 2: Validate LbaIndex parameter
+ //
+ if (FormatNvmCdw10.Lbaf > 0x1) {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ case NVME_ADMIN_SANITIZE_CMD:
+ UT_LOG_VERBOSE ("%a: Opcode = NVME_ADMIN_SANITIZE_CMD\n", __func__);
+
+ CopyMem (&SanitizeCdw1011, &Command->Cdw10, sizeof (NVME_ADMIN_SANITIZE));
+
+ //
+ // Sanitize Check 1: Validate Sanitize Action parameter
+ //
+ if (SanitizeCdw1011.Sanact > 0x4) {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Sanitize Check 2: Validate overwrite action with non-NULL overwrite pattern
+ //
+ if (((SanitizeCdw1011.Sanact == SANITIZE_ACTION_OVERWRITE) && (SanitizeCdw1011.Ovrpat != 0xDEADBEEF)) ||
+ ((SanitizeCdw1011.Sanact != SANITIZE_ACTION_OVERWRITE) && (SanitizeCdw1011.Ovrpat != 0)))
+ {
+ Cqe->Sct = NVME_CQE_SCT_GENERIC_CMD_STATUS;
+ Cqe->Sc = NVME_CQE_SC_INVALID_FIELD_IN_CMD;
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ default:
+ UT_LOG_VERBOSE ("%a: Invalid Opcode = 0x%x!!!\n", __func__, Command->Cdw0.Opcode);
+ break;
+ }
+
+ //
+ // Populate CQE (completion queue entry based on opcode and parameters
+ //
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Helper function to simulate read.
+
+ @param[in] Private Private Data.
+ @param[in] NamespaceId Name Space Id.
+ @param[in] Buffer Transfer Buffer.
+
+ **/
+EFI_STATUS
+NvmeIdentifyNamespace (
+ IN NVME_CONTROLLER_PRIVATE_DATA *Private,
+ IN UINT32 NamespaceId,
+ IN VOID *Buffer
+ )
+{
+ EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket;
+ EFI_NVM_EXPRESS_COMMAND Command;
+ EFI_NVM_EXPRESS_COMPLETION Completion;
+
+ ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET));
+ ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND));
+ ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION));
+
+ CommandPacket.NvmeCmd = &Command;
+ CommandPacket.NvmeCompletion = &Completion;
+ Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD;
+ Command.Nsid = NamespaceId;
+ CommandPacket.TransferBuffer = Buffer;
+ CommandPacket.TransferLength = sizeof (NVME_ADMIN_NAMESPACE_DATA);
+ CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT;
+ CommandPacket.QueueType = NVME_ADMIN_QUEUE;
+
+ //
+ // Set bit 0 (Cns bit) to 1 to identify a namespace
+ //
+ CommandPacket.NvmeCmd->Cdw10 = 0;
+ CommandPacket.NvmeCmd->Flags = CDW10_VALID;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Helper function to simulate read.
+
+ @param[in] Device Private Data.
+ @param[out] Buffer Buffer to read into.
+ @param[in] Lba Logical Block Addess to read from.
+ @param[in] Blocks Number of blocks.
+
+ **/
+EFI_STATUS
+NvmeUnitTestRead (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ OUT VOID *Buffer,
+ IN UINT64 Lba,
+ IN UINTN Blocks
+ )
+{
+ UT_ASSERT_NOT_NULL (Device);
+ Buffer = NULL;
+ Lba = 0;
+ Blocks = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Helper function to simulate write.
+
+ @param[in] Device Private Data.
+ @param[in] Buffer Buffer to write.
+ @param[in] Lba Logical Block Addess to write.
+ @param[in] Blocks Number of blocks.
+
+ **/
+EFI_STATUS
+NvmeUnitTestWrite (
+ IN NVME_DEVICE_PRIVATE_DATA *Device,
+ IN VOID *Buffer,
+ IN UINT64 Lba,
+ IN UINTN Blocks
+ )
+{
+ UT_ASSERT_NOT_NULL (Device);
+ Buffer = NULL;
+ Lba = 0;
+ Blocks = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Simulated BlockIo read block function.
+
+ @param[in] This BlockIo Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in] BufferSize Size of Buffer.
+ @param[out] Buffer Actual buffer to use to read.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReadBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+ Status = NvmeUnitTestRead (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ Simulated BlockIo write block function.
+
+ @param[in] This BlockIo Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in] BufferSize Size of Buffer.
+ @param[in] Buffer Actual buffer to use to write.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoWriteBlocks (
+ IN EFI_BLOCK_IO_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This);
+ Status = NvmeUnitTestWrite (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ Simulated BlockIo read block ex function.
+
+ @param[in] This BlockIo2 Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in,out] Token Block Io2 token.
+
+ @param[in] BufferSize Size of Buffer.
+ @param[out] Buffer Actual buffer to use to read.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoReadBlocksEx (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
+ Status = NvmeUnitTestRead (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ Simulated BlockIo write block ex function.
+
+ @param[in] This BlockIo2 Protocol.
+ @param[in] MediaId Id of the media.
+ @param[in] Lba Logical Block Address.
+ @param[in,out] Token Block Io2 token.
+ @param[in] BufferSize Size of Buffer.
+
+ @param[in] Buffer Actual buffer to use to write.
+
+ **/
+EFI_STATUS
+EFIAPI
+NvmeBlockIoWriteBlocksEx (
+ IN EFI_BLOCK_IO2_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_BLOCK_IO2_TOKEN *Token,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ NVME_DEVICE_PRIVATE_DATA *Device;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN NumberOfBlocks;
+ UINTN IoAlign;
+ EFI_STATUS Status;
+
+ //
+ // Check parameters.
+ //
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Media = This->Media;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockSize = Media->BlockSize;
+ if ((BufferSize % BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ NumberOfBlocks = BufferSize / BlockSize;
+ if ((Lba + NumberOfBlocks - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IoAlign = Media->IoAlign;
+ if ((IoAlign > 0) && (((UINTN)Buffer & (IoAlign - 1)) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This);
+ Status = NvmeUnitTestWrite (Device, Buffer, Lba, NumberOfBlocks);
+
+ return Status;
+}
+
+/**
+ MediaSanitizePurgeUnitTest to initialize a Private Namespace instance.
+
+ @param[in] ppDevice Nvme Private Data structure to destory and free.
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeDestroyDeviceInstance (
+ NVME_DEVICE_PRIVATE_DATA **ppDevice
+ )
+{
+ //
+ // Free in following order to to avoid dangling pointers:
+ //
+ // 1 - NVME_ADMIN_CONTROLLER_DATA
+ // 2 - NVME_CONTROLLER_PRIVATE_DATA
+ // 3 - NVME_DEVICE_PRIVATE_DATA
+ //
+ FreePool ((*ppDevice)->Controller->ControllerData);
+ (*ppDevice)->Controller->ControllerData = NULL;
+
+ FreePool ((*ppDevice)->Controller);
+ (*ppDevice)->Controller = NULL;
+
+ FreePool ((*ppDevice));
+ *ppDevice = NULL;
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ MediaSanitizePurgeUnitTest to initialize a Private Namespace instance.
+
+ @param[in] ppDevice Nvme Private Data structure to initialize.
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeCreateDeviceInstance (
+ NVME_DEVICE_PRIVATE_DATA **ppDevice
+ )
+{
+ NVME_ADMIN_NAMESPACE_DATA *NamespaceData;
+ NVME_CONTROLLER_PRIVATE_DATA *Private;
+ NVME_DEVICE_PRIVATE_DATA *Device;
+
+ Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA));
+
+ Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE;
+ Private->Cid[0] = 0;
+ Private->Cid[1] = 0;
+ Private->Cid[2] = 0;
+ Private->Pt[0] = 0;
+ Private->Pt[1] = 0;
+ Private->Pt[2] = 0;
+ Private->SqTdbl[0].Sqt = 0;
+ Private->SqTdbl[1].Sqt = 0;
+ Private->SqTdbl[2].Sqt = 0;
+ Private->CqHdbl[0].Cqh = 0;
+ Private->CqHdbl[1].Cqh = 0;
+ Private->CqHdbl[2].Cqh = 0;
+ Private->AsyncSqHead = 0;
+
+ Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_CONTROLLER_DATA));
+
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_CONTROLLER_PRIVATE_DATA\n", __func__);
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_ADMIN_CONTROLLER_DATA\n", __func__);
+
+ Private->ControllerData->Nn = 1; // One namespace
+ Private->ControllerData->Sanicap.Bes = 1; // Block Erase Supported
+ Private->ControllerData->Sanicap.Ces = 1; // Crypto Erase Supported
+ Private->ControllerData->Sanicap.Ows = 1; // Overwrite Supported
+
+ NamespaceData = AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_ADMIN_NAMESPACE_DATA\n", __func__);
+
+ Device = (NVME_DEVICE_PRIVATE_DATA *)(AllocateZeroPool (sizeof (NVME_DEVICE_PRIVATE_DATA)));
+
+ //
+ // Initialize SSD namespace instance data
+ //
+ Device->Signature = NVME_DEVICE_PRIVATE_DATA_SIGNATURE;
+ Device->NamespaceId = 0;
+ Device->NamespaceUuid = 1;
+
+ Device->Controller = Private;
+
+ //
+ // Build BlockIo media structure
+ //
+ Device->Media.MediaId = 0;
+ Device->Media.RemovableMedia = FALSE;
+ Device->Media.MediaPresent = TRUE;
+ Device->Media.LogicalPartition = FALSE;
+ Device->Media.ReadOnly = FALSE;
+ Device->Media.WriteCaching = FALSE;
+ Device->Media.BlockSize = (UINT32)(1 << 9); // 512 byte sector size
+
+ Device->Media.LastBlock = 0x4000; // NamespaceData=>Nsze
+ Device->Media.LogicalBlocksPerPhysicalBlock = 1;
+ Device->Media.LowestAlignedLba = 1;
+
+ Device->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2;
+ Device->BlockIo.Media = &Device->Media;
+ Device->BlockIo.ReadBlocks = NvmeBlockIoReadBlocks;
+ Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks;
+
+ Device->BlockIo2.Media = &Device->Media;
+ Device->BlockIo2.ReadBlocksEx = NvmeBlockIoReadBlocksEx;
+ Device->BlockIo2.WriteBlocksEx = NvmeBlockIoWriteBlocksEx;
+
+ Device->MediaSanitize.Revision = MEDIA_SANITIZE_PROTOCOL_REVISION;
+ Device->MediaSanitize.Media = &Device->Media;
+ Device->MediaSanitize.MediaClear = NvmExpressMediaClear;
+ Device->MediaSanitize.MediaPurge = NvmExpressMediaPurge;
+ Device->MediaSanitize.MediaFormat = NvmExpressMediaFormat;
+
+ Device->Controller->Passthru.Mode = 0;
+ Device->Controller->Passthru.PassThru = NvmeDeviceUnitTestPassthru;
+ Device->Controller->Passthru.BuildDevicePath = NULL;
+ Device->Controller->Passthru.GetNamespace = NULL;
+ Device->Controller->Passthru.GetNextNamespace = NULL;
+
+ CopyMem (&Device->NamespaceData, NamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA));
+ *ppDevice = Device;
+
+ UT_LOG_VERBOSE ("%a: Allocated and Initialized NVME_DEVICE_PRIVATE_DATA\n", __func__);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ MediaSanitizePurgeUnitTest to Test calls to NvmExpressMediaPurge.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+MediaSanitizePurgeUnitTest (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 PurgeAction;
+ UINT32 OverwritePattern;
+ UNIT_TEST_STATUS UnitTestStatus;
+ NVME_DEVICE_PRIVATE_DATA *NvmeDevice;
+ EFI_STATUS Status;
+
+ UnitTestStatus = UNIT_TEST_PASSED;
+ NvmeDevice = NULL;
+ Status = EFI_SUCCESS;
+
+ UnitTestStatus = NvmeCreateDeviceInstance (&NvmeDevice);
+
+ UT_ASSERT_STATUS_EQUAL (UnitTestStatus, UNIT_TEST_PASSED);
+ UT_ASSERT_NOT_NULL (NvmeDevice);
+
+ UT_LOG_VERBOSE ("%a: Create Device Instance Status = 0x%x\n", __func__, UnitTestStatus);
+ UT_LOG_VERBOSE ("%a: Device = 0x%x\n", __func__, NvmeDevice);
+ UT_LOG_VERBOSE ("%a: Device->BlockIo = 0x%x\n", __func__, NvmeDevice->BlockIo);
+ UT_LOG_VERBOSE ("%a: Device->Signature = 0x%x\n", __func__, NvmeDevice->Signature);
+
+ //
+ // Case 1: Block Erase
+ //
+ PurgeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ OverwritePattern = 0;
+
+ Status = NvmExpressMediaPurge (
+ &NvmeDevice->MediaSanitize,
+ NvmeDevice->Media.MediaId,
+ PurgeAction,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ UnitTestStatus = NvmeDestroyDeviceInstance (&NvmeDevice);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ NvmeSanitizeUnitTest to Test calls to NvmExpressSanitize.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeSanitizeUnitTest (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 NamespaceId;
+ UINT32 SanitizeAction;
+ UINT32 NoDeallocateAfterSanitize;
+ UINT32 OverwritePattern;
+ UNIT_TEST_STATUS UnitTestStatus;
+ NVME_DEVICE_PRIVATE_DATA *NvmeDevice;
+ EFI_STATUS Status;
+
+ NamespaceId = 0;
+ UnitTestStatus = UNIT_TEST_PASSED;
+ NvmeDevice = NULL;
+ Status = EFI_SUCCESS;
+ SanitizeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ UnitTestStatus = NvmeCreateDeviceInstance (&NvmeDevice);
+
+ UT_ASSERT_STATUS_EQUAL (UnitTestStatus, UNIT_TEST_PASSED);
+ UT_ASSERT_NOT_NULL (NvmeDevice);
+
+ UT_LOG_VERBOSE ("%a: Create Device Instance Status = 0x%x\n", __func__, UnitTestStatus);
+ UT_LOG_VERBOSE ("%a: Device = 0x%x\n", __func__, NvmeDevice);
+ UT_LOG_VERBOSE ("%a: Device->BlockIo = 0x%x\n", __func__, NvmeDevice->BlockIo);
+ UT_LOG_VERBOSE ("%a: Device->Signature = 0x%x\n", __func__, NvmeDevice->Signature);
+
+ //
+ // Case 1: Block Erase
+ //
+ SanitizeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 2: Crypto Erase
+ //
+ SanitizeAction = SANITIZE_ACTION_CRYPTO_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 3: Overwrite
+ //
+ SanitizeAction = SANITIZE_ACTION_OVERWRITE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0xDEADBEEF;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 4: Block Erase (invalid overwrite pattern)
+ //
+ SanitizeAction = SANITIZE_ACTION_BLOCK_ERASE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0xDEADBEEF;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ //
+ // Case 5: Overwrite (invalid overwrite pattern)
+ //
+ SanitizeAction = SANITIZE_ACTION_OVERWRITE;
+ NoDeallocateAfterSanitize = 0;
+ OverwritePattern = 0;
+
+ Status = NvmExpressSanitize (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ SanitizeAction,
+ NoDeallocateAfterSanitize,
+ OverwritePattern
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ UnitTestStatus = NvmeDestroyDeviceInstance (&NvmeDevice);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ NvmeFormatNvmUnitTest to Test calls to NvmExpressFormatNvm.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+NvmeFormatNvmUnitTest (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 NamespaceId;
+ UINT32 Ses;
+ UINT32 Flbas;
+ NVME_DEVICE_PRIVATE_DATA *NvmeDevice;
+ UNIT_TEST_STATUS UnitTestStatus;
+ EFI_STATUS Status;
+
+ NamespaceId = 0;
+ NvmeDevice = NULL;
+ UnitTestStatus = UNIT_TEST_PASSED;
+ Status = EFI_SUCCESS;
+
+ UnitTestStatus = NvmeCreateDeviceInstance (&NvmeDevice);
+
+ UT_ASSERT_STATUS_EQUAL (UnitTestStatus, UNIT_TEST_PASSED);
+ UT_ASSERT_NOT_NULL (NvmeDevice);
+
+ UT_LOG_VERBOSE ("%a: Create Device Instance Status = 0x%x\n", __func__, UnitTestStatus);
+ UT_LOG_VERBOSE ("%a: Device = 0x%x\n", __func__, NvmeDevice);
+ UT_LOG_VERBOSE ("%a: Device->BlockIo = 0x%x\n", __func__, NvmeDevice->BlockIo);
+ UT_LOG_VERBOSE ("%a: Device->Signature = 0x%x\n", __func__, NvmeDevice->Signature);
+
+ //
+ // Case 1: User Data Erase (Flbas = 0)
+ //
+ Ses = SES_USER_DATA_ERASE;
+ Flbas = 0;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 2: Crypto Erase (Flbas = 0)
+ //
+ Ses = SES_CRYPTO_ERASE;
+ Flbas = 0;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Case 3: User Data Erase (Invalid Flbas = 3)
+ //
+ Ses = SES_USER_DATA_ERASE;
+ Flbas = 3;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ //
+ // Case 4: Invalid SES (Flba = 0)
+ //
+ Ses = 0xFF;
+ Flbas = 0;
+ Status = NvmExpressFormatNvm (
+ &NvmeDevice->BlockIo,
+ NamespaceId,
+ Ses,
+ Flbas
+ );
+
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ UnitTestStatus = NvmeDestroyDeviceInstance (&NvmeDevice);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Baseline Unit Test.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestBaseline (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 A;
+ UINT32 B;
+ UINT32 C;
+
+ A = 1;
+ B = 1;
+ C = A + B;
+
+ UT_ASSERT_EQUAL (C, 2);
+ UT_ASSERT_NOT_EQUAL (0, 1);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks a variable using the Variable Policy Protocol with a
+ policy other than LOCK_NOW then attempts to lock the same variable using the
+ Variable Lock Protocol. The call to Variable Policy is expected to succeed
+ and the call to Variable Lock is expected to fail.
+
+ @retval EFI_SUCCES Success
+ @retval Other Error
+ **/
+EFI_STATUS
+EFIAPI
+MediaSanitizeUnitTestEntry (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE NvmeFormatNvmTestSuite;
+ UNIT_TEST_SUITE_HANDLE NvmeSanitizeTestSuite;
+ UNIT_TEST_SUITE_HANDLE MediaSanitizeProtocolTestSuite;
+
+ Framework = NULL;
+
+ #define UNIT_TEST_NAME "Media Sanitize Protocol Unit Test"
+ #define UNIT_TEST_VERSION "1.0"
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (
+ &Framework,
+ UNIT_TEST_NAME,
+ gEfiCallerBaseName,
+ UNIT_TEST_VERSION
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Populate the NVM Express Format NVM Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (
+ &NvmeFormatNvmTestSuite,
+ Framework,
+ "NVM Express Format NVM Test Suite",
+ "Nvm.Express.Format.Nvm",
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for NvmeFormatNvmTestSuite. Status = %r\n", Status));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ //
+ // Add baseline sanity test case
+ //
+ AddTestCase (
+ NvmeFormatNvmTestSuite, // Test Suite Handle
+ "Baseline Format NVM Unit Test", // Test Description
+ "FormatNVM", // Test Class
+ UnitTestBaseline, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Add test case for NvmExpressFormatNvm()
+ //
+ AddTestCase (
+ NvmeFormatNvmTestSuite, // Test Suite Handle
+ "Admin Format NVM Command Unit Test", // Test Description
+ "FormatNVM", // Test Class
+ NvmeFormatNvmUnitTest, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Populate the NVM Express Sanitize Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (
+ &NvmeSanitizeTestSuite,
+ Framework,
+ "NVM Express Sanitize Test Suite",
+ "Nvm.Express.Sanitize",
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for NvmeSanitizTestSuite. Status = %r\n", Status));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ //
+ // Add baseline sanity test
+ //
+ AddTestCase (
+ NvmeSanitizeTestSuite, // Test Suite Handle
+ "Baseline Sanitize Unit Test", // Test Description
+ "Sanitize", // Test Class
+ UnitTestBaseline, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Add test case for NvmExressSanitize()
+ //
+ AddTestCase (
+ NvmeSanitizeTestSuite, // Test Suite Handle
+ "Admin Sanitize Command Unit Test", // Test Description
+ "Sanitize", // Test Class
+ NvmeSanitizeUnitTest, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Populate the Media Sanitize Protocol Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (
+ &MediaSanitizeProtocolTestSuite,
+ Framework,
+ "Media Sanitize Protocol Test Suite",
+ "Media.Sanitize.Protocol",
+ NULL,
+ NULL
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MediaSanitizeProtocolTestSuite. Status = %r\n", Status));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+
+ //
+ // Add test case for Media Purge
+ //
+ AddTestCase (
+ MediaSanitizeProtocolTestSuite, // Test Suite Handle
+ "Baseline MediaSanitize Unit Test", // Test Description
+ "MediaSanitize", // Test Class
+ UnitTestBaseline, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Add test case for Media Purge
+ //
+ AddTestCase (
+ MediaSanitizeProtocolTestSuite, // Test Suite Handle
+ "Protocol Media Sanitize Unit Test", // Test Description
+ "MediaPurge", // Test Class
+ MediaSanitizePurgeUnitTest, // UNIT_TEST_FUNCTION()
+ NULL, // (Optional) UNIT_TEST_PREREQUISITE()
+ NULL, // (Optional) UNIT_TEST_CLEANUP()
+ NULL // (Optional) UNIT_TEST_CONTEXT
+ );
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+///
+/// Avoid ECC error for function name that starts with lower case letter
+///
+#define MediaSanitizeUnitTestMain main
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+
+ @param[in] Argc Number of arguments
+ @param[in] Argv Array of pointers to arguments
+
+ @retval 0 Success
+ @retval other Error
+**/
+INT32
+MediaSanitizeUnitTestMain (
+ IN INT32 Argc,
+ IN CHAR8 *Argv[]
+ )
+{
+ return MediaSanitizeUnitTestEntry ();
+}
diff --git a/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf b/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf
new file mode 100644
index 0000000..feeeea3
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf
@@ -0,0 +1,37 @@
+## @file
+# Unit tests for MEDIA_SANITIZE_PROTOCOL and mapping to NVM Express native commands (Sanitize and FormatNVM)
+#
+# Copyright (C) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = MediaSanitizeUnitTestHost
+ FILE_GUID = AAE328E9-37C3-4F4A-A2C0-0BE0E681ADA6
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MediaSanitizeUnitTest.c
+ ../NvmExpressMediaSanitize.c
+ ../NvmExpressMediaSanitize.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ UnitTestLib
+ PrintLib
+ MemoryAllocationLib
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
index 337b209..a21c94c 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.c
@@ -49,7 +49,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugReque
Installs driver module protocols and. Creates virtual device handles for ConIn,
ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
- Installs Graphics Output protocol and/or UGA Draw protocol if needed.
+ Installs Graphics Output protocol if needed.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index 6594b8e..5c4b215 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -59,19 +59,30 @@ PciDevicePresent (
Pci
);
- if (!EFI_ERROR (Status) && ((Pci->Hdr).VendorId != 0xffff)) {
- //
- // Read the entire config header for the device
- //
- Status = PciRootBridgeIo->Pci.Read (
- PciRootBridgeIo,
- EfiPciWidthUint32,
- Address,
- sizeof (PCI_TYPE00) / sizeof (UINT32),
- Pci
- );
+ //
+ // The host bridge may be programmed to accept Configuration Retry Status (CRS). If the PCI device
+ // is slow, and CRS is enabled, the VendorId may read as 0x0001 when not ready.
+ // This behavior is defined in PCI spec that VendorId is 0x0001.
+ // PCI EXPRESS BASE SPECIFICATION, REV. 3.1 section 2.3.1.
+ // Skip the device, as all the other data read will be invalid.
+ //
+ if (!EFI_ERROR (Status)) {
+ if (((Pci->Hdr).VendorId != 0xffff) && ((Pci->Hdr).VendorId != 0x0001)) {
+ //
+ // Read the entire config header for the device
+ //
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo,
+ EfiPciWidthUint32,
+ Address,
+ sizeof (PCI_TYPE00) / sizeof (UINT32),
+ Pci
+ );
- return EFI_SUCCESS;
+ return EFI_SUCCESS;
+ } else if ((Pci->Hdr).VendorId == 0x0001) {
+ DEBUG ((DEBUG_WARN, "CRS response detected. Devices that return a CRS response during enumeration are currently ignored\n"));
+ }
}
return EFI_NOT_FOUND;
@@ -2628,7 +2639,7 @@ PciEnumeratorLight (
**/
EFI_STATUS
PciGetBusRange (
- IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
+ IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
OUT UINT16 *MinBus,
OUT UINT16 *MaxBus,
OUT UINT16 *BusRange
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
index 7daa6e0..89df989 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
@@ -409,7 +409,7 @@ PciEnumeratorLight (
**/
EFI_STATUS
PciGetBusRange (
- IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
+ IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
OUT UINT16 *MinBus,
OUT UINT16 *MaxBus,
OUT UINT16 *BusRange
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
index 84fc016..28840de 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
@@ -1100,6 +1100,7 @@ PciScanBus (
EFI_HPC_STATE State;
UINT64 PciAddress;
EFI_HPC_PADDING_ATTRIBUTES Attributes;
+ VOID *DescriptorsBuffer;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *NextDescriptors;
UINT16 BusRange;
@@ -1108,16 +1109,17 @@ PciScanBus (
UINT32 TempReservedBusNum;
BOOLEAN IsAriEnabled;
- PciRootBridgeIo = Bridge->PciRootBridgeIo;
- SecondBus = 0;
- Register = 0;
- State = 0;
- Attributes = (EFI_HPC_PADDING_ATTRIBUTES)0;
- BusRange = 0;
- BusPadding = FALSE;
- PciDevice = NULL;
- PciAddress = 0;
- IsAriEnabled = FALSE;
+ PciRootBridgeIo = Bridge->PciRootBridgeIo;
+ SecondBus = 0;
+ Register = 0;
+ State = 0;
+ Attributes = (EFI_HPC_PADDING_ATTRIBUTES)0;
+ BusRange = 0;
+ BusPadding = FALSE;
+ PciDevice = NULL;
+ PciAddress = 0;
+ IsAriEnabled = FALSE;
+ DescriptorsBuffer = NULL;
for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
if (!IsAriEnabled) {
@@ -1257,7 +1259,7 @@ PciScanBus (
PciDevice->DevicePath,
PciAddress,
&State,
- (VOID **)&Descriptors,
+ &DescriptorsBuffer,
&Attributes
);
@@ -1265,6 +1267,7 @@ PciScanBus (
return Status;
}
+ Descriptors = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)DescriptorsBuffer;
BusRange = 0;
NextDescriptors = Descriptors;
Status = PciGetBusRange (
@@ -1274,7 +1277,9 @@ PciScanBus (
&BusRange
);
- FreePool (Descriptors);
+ FreePool (DescriptorsBuffer);
+ DescriptorsBuffer = NULL;
+ Descriptors = NULL;
if (!EFI_ERROR (Status)) {
BusPadding = TRUE;
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
index bd5ace1..8bb6c12 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.c
@@ -371,7 +371,7 @@ ContainEfiImage (
@param RomBase Base address of Option Rom.
@retval EFI_OUT_OF_RESOURCES No enough memory to hold image.
- @retval EFI_SUCESS Successfully loaded Option Rom.
+ @retval EFI_SUCCESS Successfully loaded Option Rom.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h
index 16998a4..0ddad05 100644
--- a/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h
+++ b/MdeModulePkg/Bus/Pci/PciBusDxe/PciOptionRomSupport.h
@@ -91,7 +91,7 @@ GetOpRomInfo (
@param RomBase Base address of Option Rom.
@retval EFI_OUT_OF_RESOURCES No enough memory to hold image.
- @retval EFI_SUCESS Successfully loaded Option Rom.
+ @retval EFI_SUCCESS Successfully loaded Option Rom.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
index 157a0ad..419f47a 100644
--- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
+++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -1238,6 +1238,16 @@ RootBridgeIoPciAccess (
}
}
+ //
+ // If the access was a PCI write, it might have side effects that impact how
+ // the PCI device decodes its MMIO regions. Issue a barrier to ensure that
+ // subsequent MMIO accesses to those regions will not be reordered, and will
+ // not arrive before the PCI write.
+ //
+ if (!Read) {
+ MemoryFence ();
+ }
+
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c b/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c
index 8a85a6c..fa54e82 100644
--- a/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c
+++ b/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c
@@ -140,9 +140,9 @@ VerifyUartParameters (
}
Percent = DivU64x32 (MultU64x32 (BaudRate, 100), ComputedBaudRate);
- DEBUG ((DEBUG_INFO, "ClockRate = %d\n", ClockRate));
- DEBUG ((DEBUG_INFO, "Divisor = %ld\n", ComputedDivisor));
- DEBUG ((DEBUG_INFO, "BaudRate/Actual (%ld/%d) = %d%%\n", BaudRate, ComputedBaudRate, Percent));
+ DEBUG ((DEBUG_VERBOSE, "ClockRate = %d\n", ClockRate));
+ DEBUG ((DEBUG_VERBOSE, "Divisor = %ld\n", ComputedDivisor));
+ DEBUG ((DEBUG_VERBOSE, "BaudRate/Actual (%ld/%d) = %d%%\n", BaudRate, ComputedBaudRate, Percent));
//
// If the requested BaudRate is not supported:
@@ -188,9 +188,9 @@ VerifyUartParameters (
return FALSE;
}
- DEBUG ((DEBUG_INFO, "ClockRate = %d\n", ClockRate));
- DEBUG ((DEBUG_INFO, "Divisor = %ld\n", ComputedDivisor));
- DEBUG ((DEBUG_INFO, "BaudRate/Actual (%ld/%d) = %d%%\n", BaudRate, ComputedBaudRate, Percent));
+ DEBUG ((DEBUG_VERBOSE, "ClockRate = %d\n", ClockRate));
+ DEBUG ((DEBUG_VERBOSE, "Divisor = %ld\n", ComputedDivisor));
+ DEBUG ((DEBUG_VERBOSE, "BaudRate/Actual (%ld/%d) = %d%%\n", BaudRate, ComputedBaudRate, Percent));
if (ActualBaudRate != NULL) {
*ActualBaudRate = ComputedBaudRate;
diff --git a/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.c b/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.c
index ea01160..e38304c 100644
--- a/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.c
+++ b/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.c
@@ -287,9 +287,35 @@ SataControllerSupported (
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
- EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 PciData;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 PciData;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+
+ //
+ // Attempt to open DevicePath Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *)&ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ///
+ /// Close the protocol because we don't use it here
+ ///
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
//
// Attempt to open PCI I/O Protocol
diff --git a/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.h b/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.h
index 4d545fb..91d10e1 100644
--- a/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.h
+++ b/MdeModulePkg/Bus/Pci/SataControllerDxe/SataController.h
@@ -18,6 +18,7 @@
#include <Protocol/DriverBinding.h>
#include <Protocol/PciIo.h>
#include <Protocol/IdeControllerInit.h>
+#include <Protocol/DevicePath.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
diff --git a/MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf b/MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
index 488920a..e446058 100644
--- a/MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
+++ b/MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
@@ -45,6 +45,7 @@
[Protocols]
gEfiPciIoProtocolGuid ## TO_START
gEfiIdeControllerInitProtocolGuid ## BY_START
+ gEfiDevicePathProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
SataControllerDxeExtra.uni
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
index 2e7497a..9e8a7f4 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
@@ -8,6 +8,7 @@
Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2023, Apple Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -59,6 +60,7 @@ DumpCapabilityReg (
DEBUG ((DEBUG_INFO, " SDR50 Support %a\n", Capability->Sdr50 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " SDR104 Support %a\n", Capability->Sdr104 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " DDR50 Support %a\n", Capability->Ddr50 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " UHS-II Support %a\n", Capability->UhsII ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Driver Type A %a\n", Capability->DriverTypeA ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Driver Type C %a\n", Capability->DriverTypeC ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Driver Type D %a\n", Capability->DriverTypeD ? "TRUE" : "FALSE"));
@@ -72,6 +74,8 @@ DumpCapabilityReg (
DEBUG ((DEBUG_INFO, " SDR50 Tuning %a\n", Capability->TuningSDR50 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " Retuning Mode Mode %d\n", Capability->RetuningMod + 1));
DEBUG ((DEBUG_INFO, " Clock Multiplier M = %d\n", Capability->ClkMultiplier + 1));
+ DEBUG ((DEBUG_INFO, " ADMA3 Support %a\n", Capability->Adma3 ? "TRUE" : "FALSE"));
+ DEBUG ((DEBUG_INFO, " 1.8V VDD2 %a\n", Capability->Vdd2Voltage18 ? "TRUE" : "FALSE"));
DEBUG ((DEBUG_INFO, " HS 400 %a\n", Capability->Hs400 ? "TRUE" : "FALSE"));
return;
}
diff --git a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
index 9115577..e436a7d 100644
--- a/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
+++ b/MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
@@ -2,10 +2,13 @@
Provides some data structure definitions used by the SD/MMC host controller driver.
-Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2023, Apple Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ @par Specification Reference:
+ - SD Host Controller Simplified Specification, Version 4.20, July 25, 2018
**/
#ifndef _SD_MMC_PCI_HCI_H_
@@ -174,7 +177,7 @@ typedef struct {
UINT32 Sdr50 : 1; // bit 32
UINT32 Sdr104 : 1; // bit 33
UINT32 Ddr50 : 1; // bit 34
- UINT32 Reserved3 : 1; // bit 35
+ UINT32 UhsII : 1; // bit 35
UINT32 DriverTypeA : 1; // bit 36
UINT32 DriverTypeC : 1; // bit 37
UINT32 DriverTypeD : 1; // bit 38
@@ -184,7 +187,10 @@ typedef struct {
UINT32 TuningSDR50 : 1; // bit 45
UINT32 RetuningMod : 2; // bit 46:47
UINT32 ClkMultiplier : 8; // bit 48:55
- UINT32 Reserved5 : 7; // bit 56:62
+ UINT32 Reserved5 : 3; // bit 56:58
+ UINT32 Adma3 : 1; // bit 59
+ UINT32 Vdd2Voltage18 : 1; // bit 60
+ UINT32 Reserved6 : 2; // bit 61:62
UINT32 Hs400 : 1; // bit 63
} SD_MMC_HC_SLOT_CAP;
diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
index 496ffbd..8e6bd1b 100644
--- a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
+++ b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.c
@@ -875,7 +875,7 @@ Uhci2BulkTransfer (
//
// Link the TDs to bulk queue head. According to the platfore
- // defintion of UHCI_NO_BW_RECLAMATION, BulkQh is either configured
+ // definition of UHCI_NO_BW_RECLAMATION, BulkQh is either configured
// to do full speed bandwidth reclamation or not.
//
BulkQh = Uhc->BulkQh;
@@ -1330,8 +1330,7 @@ UhciDriverEntryPoint (
}
/**
- Test to see if this driver supports ControllerHandle. Any
- ControllerHandle that has UsbHcProtocol installed will be supported.
+ Test to see if this driver supports ControllerHandle.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
diff --git a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h
index 138623e..94494b2 100644
--- a/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h
+++ b/MdeModulePkg/Bus/Pci/UhciDxe/Uhci.h
@@ -13,7 +13,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Uefi.h>
#include <Protocol/Usb2HostController.h>
-#include <Protocol/UsbHostController.h>
#include <Protocol/PciIo.h>
#include <Guid/EventGroup.h>
@@ -148,8 +147,7 @@ extern EFI_COMPONENT_NAME_PROTOCOL gUhciComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gUhciComponentName2;
/**
- Test to see if this driver supports ControllerHandle. Any
- ControllerHandle that has UsbHcProtocol installed will be supported.
+ Test to see if this driver supports ControllerHandle.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index cf6b329..c830db6 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -2077,7 +2077,12 @@ XhcDriverBindingStart (
XhcSetBiosOwnership (Xhc);
- XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
+ Status = XhcResetHC (Xhc, XHC_RESET_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: failed to reset HC\n", __func__));
+ goto FREE_POOL;
+ }
+
ASSERT (XhcIsHalt (Xhc));
//
@@ -2392,7 +2397,7 @@ XhcGetElapsedTicks (
// Counter counts upwards, check for an overflow condition
//
if (*PreviousTick > CurrentTick) {
- Delta = (mXhciPerformanceCounterEndValue - *PreviousTick) + CurrentTick;
+ Delta = (CurrentTick - mXhciPerformanceCounterStartValue) + (mXhciPerformanceCounterEndValue - *PreviousTick);
} else {
Delta = CurrentTick - *PreviousTick;
}
@@ -2401,7 +2406,7 @@ XhcGetElapsedTicks (
// Counter counts downwards, check for an underflow condition
//
if (*PreviousTick < CurrentTick) {
- Delta = (mXhciPerformanceCounterStartValue - CurrentTick) + *PreviousTick;
+ Delta = (mXhciPerformanceCounterStartValue - CurrentTick) + (*PreviousTick - mXhciPerformanceCounterEndValue);
} else {
Delta = *PreviousTick - CurrentTick;
}
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
index 525942a..dc8228b 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
@@ -29,6 +29,8 @@ XhcReadCapReg8 (
UINT8 Data;
EFI_STATUS Status;
+ Data = 0;
+
Status = Xhc->PciIo->Mem.Read (
Xhc->PciIo,
EfiPciIoWidthUint8,
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index a97ed44..50d7d4b 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -6,6 +6,7 @@
Copyright (c) 2011 - 2020, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (C) 2025 Qualcomm Technologies, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -2165,6 +2166,7 @@ XhcInitializeDeviceSlot (
DEVICE_CONTEXT *ParentDeviceContext;
EFI_PHYSICAL_ADDRESS PhyAddr;
+ EvtTrb = NULL;
ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));
CmdTrb.CycleBit = 1;
CmdTrb.Type = TRB_TYPE_EN_SLOT;
@@ -2175,7 +2177,7 @@ XhcInitializeDeviceSlot (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcInitializeDeviceSlot: Enable Slot Failed, Status = %r\n", Status));
return Status;
}
@@ -2390,6 +2392,7 @@ XhcInitializeDeviceSlot64 (
DEVICE_CONTEXT_64 *ParentDeviceContext;
EFI_PHYSICAL_ADDRESS PhyAddr;
+ EvtTrb = NULL;
ZeroMem (&CmdTrb, sizeof (CMD_TRB_ENABLE_SLOT));
CmdTrb.CycleBit = 1;
CmdTrb.Type = TRB_TYPE_EN_SLOT;
@@ -2400,7 +2403,7 @@ XhcInitializeDeviceSlot64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcInitializeDeviceSlot64: Enable Slot Failed, Status = %r\n", Status));
return Status;
}
@@ -2602,6 +2605,8 @@ XhcDisableSlotCmd (
UINT8 Index;
VOID *RingSeg;
+ EvtTrb = NULL;
+
//
// Disable the device slots occupied by these devices on its downstream ports.
// Entry 0 is reserved.
@@ -2637,7 +2642,7 @@ XhcDisableSlotCmd (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));
return Status;
}
@@ -2713,6 +2718,8 @@ XhcDisableSlotCmd64 (
UINT8 Index;
VOID *RingSeg;
+ EvtTrb = NULL;
+
//
// Disable the device slots occupied by these devices on its downstream ports.
// Entry 0 is reserved.
@@ -2748,7 +2755,7 @@ XhcDisableSlotCmd64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcDisableSlotCmd: Disable Slot Command Failed, Status = %r\n", Status));
return Status;
}
@@ -2803,6 +2810,60 @@ XhcDisableSlotCmd64 (
}
/**
+ Get the bInterval from descriptor and calculate the value to be used to initialize
+ the interval field of the endpoint context.
+
+ Refer to XHCI 1.1 spec section 6.2.3.6, tables 61 & 65
+
+ @param EpType The endpoint type (only USB_ENDPOINT_ISO or USB_ENDPOINT_INTERRUPT).
+ @param DeviceSpeed The connected device's speed.
+ @param Interval The interval value from the descriptor.
+
+ @retval The calculated interval value to be applied to the endpoint context.
+
+**/
+static UINT8
+CalculateInterval (
+ UINT8 EpType,
+ UINT8 DeviceSpeed,
+ UINT8 Interval
+ )
+{
+ UINT8 OriginalInterval = Interval;
+
+ if ((EpType == USB_ENDPOINT_ISO) && (DeviceSpeed == EFI_USB_SPEED_FULL)) {
+ ASSERT (Interval >= 1 && Interval <= 16);
+ Interval = Interval + 2;
+ } else if ((EpType == USB_ENDPOINT_INTERRUPT) && ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW))) {
+ ASSERT (Interval != 0);
+ Interval = (UINT8)HighBitSet32 ((UINT32)Interval) + 3;
+ } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
+ ASSERT (Interval != 0);
+
+ //
+ // Some devices incorrectly report full-speed bInterval values in
+ // their high/super-speed interrupt endpoint descriptors. Try to
+ // adjust those assuming they were expressed in units of ms with an
+ // upper limit of 128ms.
+ //
+ if (Interval > 16) {
+ Interval = (UINT8)HighBitSet32 ((UINT32)Interval*8);
+
+ DEBUG ((
+ DEBUG_WARN,
+ "EpDesc->Interval (%u) out of range. Adjusted to %u\n",
+ OriginalInterval,
+ Interval
+ ));
+ } else {
+ Interval = Interval - 1;
+ }
+ }
+
+ return Interval;
+}
+
+/**
Initialize endpoint context in input context.
@param Xhc The XHCI Instance.
@@ -2832,7 +2893,6 @@ XhcInitializeEndpointContext (
UINT8 Dci;
UINT8 MaxDci;
EFI_PHYSICAL_ADDRESS PhyAddr;
- UINT8 Interval;
TRANSFER_RING *EndpointTransferRing;
MaxDci = 0;
@@ -2842,7 +2902,7 @@ XhcInitializeEndpointContext (
MaxDci = 1;
}
- EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
@@ -2908,19 +2968,7 @@ XhcInitializeEndpointContext (
InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;
}
- //
- // Get the bInterval from descriptor and init the the interval field of endpoint context.
- // Refer to XHCI 1.1 spec section 6.2.3.6.
- //
- if (DeviceSpeed == EFI_USB_SPEED_FULL) {
- Interval = EpDesc->Interval;
- ASSERT (Interval >= 1 && Interval <= 16);
- InputContext->EP[Dci-1].Interval = Interval + 2;
- } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
- Interval = EpDesc->Interval;
- ASSERT (Interval >= 1 && Interval <= 16);
- InputContext->EP[Dci-1].Interval = Interval - 1;
- }
+ InputContext->EP[Dci-1].Interval = CalculateInterval (USB_ENDPOINT_ISO, DeviceSpeed, EpDesc->Interval);
//
// Do not support isochronous transfer now.
@@ -2939,23 +2987,9 @@ XhcInitializeEndpointContext (
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize;
- //
- // Get the bInterval from descriptor and init the the interval field of endpoint context
- //
- if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {
- Interval = EpDesc->Interval;
- //
- // Calculate through the bInterval field of Endpoint descriptor.
- //
- ASSERT (Interval != 0);
- InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32 ((UINT32)Interval) + 3;
- } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
- Interval = EpDesc->Interval;
- ASSERT (Interval >= 1 && Interval <= 16);
- //
- // Refer to XHCI 1.0 spec section 6.2.3.6, table 61
- //
- InputContext->EP[Dci-1].Interval = Interval - 1;
+ InputContext->EP[Dci-1].Interval = CalculateInterval (USB_ENDPOINT_INTERRUPT, DeviceSpeed, EpDesc->Interval);
+
+ if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
InputContext->EP[Dci-1].MaxESITPayload = 0x0002;
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
@@ -3035,7 +3069,6 @@ XhcInitializeEndpointContext64 (
UINT8 Dci;
UINT8 MaxDci;
EFI_PHYSICAL_ADDRESS PhyAddr;
- UINT8 Interval;
TRANSFER_RING *EndpointTransferRing;
MaxDci = 0;
@@ -3045,7 +3078,7 @@ XhcInitializeEndpointContext64 (
MaxDci = 1;
}
- EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
@@ -3111,19 +3144,7 @@ XhcInitializeEndpointContext64 (
InputContext->EP[Dci-1].EPType = ED_ISOCH_OUT;
}
- //
- // Get the bInterval from descriptor and init the the interval field of endpoint context.
- // Refer to XHCI 1.1 spec section 6.2.3.6.
- //
- if (DeviceSpeed == EFI_USB_SPEED_FULL) {
- Interval = EpDesc->Interval;
- ASSERT (Interval >= 1 && Interval <= 16);
- InputContext->EP[Dci-1].Interval = Interval + 2;
- } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
- Interval = EpDesc->Interval;
- ASSERT (Interval >= 1 && Interval <= 16);
- InputContext->EP[Dci-1].Interval = Interval - 1;
- }
+ InputContext->EP[Dci-1].Interval = CalculateInterval (USB_ENDPOINT_ISO, DeviceSpeed, EpDesc->Interval);
//
// Do not support isochronous transfer now.
@@ -3142,23 +3163,9 @@ XhcInitializeEndpointContext64 (
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
InputContext->EP[Dci-1].MaxESITPayload = EpDesc->MaxPacketSize;
- //
- // Get the bInterval from descriptor and init the the interval field of endpoint context
- //
- if ((DeviceSpeed == EFI_USB_SPEED_FULL) || (DeviceSpeed == EFI_USB_SPEED_LOW)) {
- Interval = EpDesc->Interval;
- //
- // Calculate through the bInterval field of Endpoint descriptor.
- //
- ASSERT (Interval != 0);
- InputContext->EP[Dci-1].Interval = (UINT32)HighBitSet32 ((UINT32)Interval) + 3;
- } else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
- Interval = EpDesc->Interval;
- ASSERT (Interval >= 1 && Interval <= 16);
- //
- // Refer to XHCI 1.0 spec section 6.2.3.6, table 61
- //
- InputContext->EP[Dci-1].Interval = Interval - 1;
+ InputContext->EP[Dci-1].Interval = CalculateInterval (USB_ENDPOINT_INTERRUPT, DeviceSpeed, EpDesc->Interval);
+
+ if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
InputContext->EP[Dci-1].AverageTRBLength = 0x1000;
InputContext->EP[Dci-1].MaxESITPayload = 0x0002;
InputContext->EP[Dci-1].MaxBurstSize = 0x0;
@@ -3240,6 +3247,8 @@ XhcSetConfigCmd (
DEVICE_CONTEXT *OutputContext;
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
+ EvtTrb = NULL;
+
//
// 4.6.6 Configure Endpoint
//
@@ -3252,7 +3261,7 @@ XhcSetConfigCmd (
MaxDci = 0;
- IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)ConfigDesc + ConfigDesc->Length);
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
@@ -3290,7 +3299,7 @@ XhcSetConfigCmd (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcSetConfigCmd: Config Endpoint Failed, Status = %r\n", Status));
} else {
Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;
@@ -3331,6 +3340,8 @@ XhcSetConfigCmd64 (
DEVICE_CONTEXT_64 *OutputContext;
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
+ EvtTrb = NULL;
+
//
// 4.6.6 Configure Endpoint
//
@@ -3343,7 +3354,7 @@ XhcSetConfigCmd64 (
MaxDci = 0;
- IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)ConfigDesc + ConfigDesc->Length);
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
@@ -3381,7 +3392,7 @@ XhcSetConfigCmd64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcSetConfigCmd64: Config Endpoint Failed, Status = %r\n", Status));
} else {
Xhc->UsbDevContext[SlotId].ActiveConfiguration = ConfigDesc->ConfigurationValue;
@@ -3417,6 +3428,8 @@ XhcStopEndpoint (
DEBUG ((DEBUG_VERBOSE, "XhcStopEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci));
+ EvtTrb = NULL;
+
//
// When XhcCheckUrbResult waits for the Stop_Endpoint completion, it also checks
// the PendingUrb completion status, because it's possible that the PendingUrb is
@@ -3454,7 +3467,7 @@ XhcStopEndpoint (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcStopEndpoint: Stop Endpoint Failed, Status = %r\n", Status));
}
@@ -3488,6 +3501,8 @@ XhcResetEndpoint (
DEBUG ((DEBUG_INFO, "XhcResetEndpoint: Slot = 0x%x, Dci = 0x%x\n", SlotId, Dci));
+ EvtTrb = NULL;
+
//
// Send stop endpoint command to transit Endpoint from running to stop state
//
@@ -3502,7 +3517,7 @@ XhcResetEndpoint (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcResetEndpoint: Reset Endpoint Failed, Status = %r\n", Status));
}
@@ -3538,6 +3553,8 @@ XhcSetTrDequeuePointer (
DEBUG ((DEBUG_VERBOSE, "XhcSetTrDequeuePointer: Slot = 0x%x, Dci = 0x%x, Urb = 0x%x\n", SlotId, Dci, Urb));
+ EvtTrb = NULL;
+
//
// Send stop endpoint command to transit Endpoint from running to stop state
//
@@ -3555,7 +3572,7 @@ XhcSetTrDequeuePointer (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcSetTrDequeuePointer: Set TR Dequeue Pointer Failed, Status = %r\n", Status));
}
@@ -3604,6 +3621,7 @@ XhcSetInterface (
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
Status = EFI_SUCCESS;
+ EvtTrb = NULL;
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
@@ -3627,7 +3645,7 @@ XhcSetInterface (
IfDescActive = NULL;
IfDescSet = NULL;
- IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)ConfigDesc + ConfigDesc->Length);
while ((UINTN)IfDesc < ((UINTN)ConfigDesc + ConfigDesc->TotalLength)) {
if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) {
if (IfDesc->InterfaceNumber == (UINT8)Request->Index) {
@@ -3755,7 +3773,7 @@ XhcSetInterface (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "SetInterface: Config Endpoint Failed, Status = %r\n", Status));
} else {
//
@@ -3810,6 +3828,7 @@ XhcSetInterface64 (
EVT_TRB_COMMAND_COMPLETION *EvtTrb;
Status = EFI_SUCCESS;
+ EvtTrb = NULL;
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
@@ -3833,7 +3852,7 @@ XhcSetInterface64 (
IfDescActive = NULL;
IfDescSet = NULL;
- IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)ConfigDesc + ConfigDesc->Length);
while ((UINTN)IfDesc < ((UINTN)ConfigDesc + ConfigDesc->TotalLength)) {
if ((IfDesc->DescriptorType == USB_DESC_TYPE_INTERFACE) && (IfDesc->Length >= sizeof (USB_INTERFACE_DESCRIPTOR))) {
if (IfDesc->InterfaceNumber == (UINT8)Request->Index) {
@@ -3961,7 +3980,7 @@ XhcSetInterface64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "SetInterface64: Config Endpoint Failed, Status = %r\n", Status));
} else {
//
@@ -4001,6 +4020,8 @@ XhcEvaluateContext (
ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
+ EvtTrb = NULL;
+
//
// 4.6.7 Evaluate Context
//
@@ -4028,7 +4049,7 @@ XhcEvaluateContext (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcEvaluateContext: Evaluate Context Failed, Status = %r\n", Status));
}
@@ -4062,6 +4083,8 @@ XhcEvaluateContext64 (
ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
+ EvtTrb = NULL;
+
//
// 4.6.7 Evaluate Context
//
@@ -4089,7 +4112,7 @@ XhcEvaluateContext64 (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcEvaluateContext64: Evaluate Context Failed, Status = %r\n", Status));
}
@@ -4125,6 +4148,7 @@ XhcConfigHubContext (
EFI_PHYSICAL_ADDRESS PhyAddr;
ASSERT (Xhc->UsbDevContext[SlotId].SlotId != 0);
+ EvtTrb = NULL;
InputContext = Xhc->UsbDevContext[SlotId].InputContext;
OutputContext = Xhc->UsbDevContext[SlotId].OutputContext;
@@ -4158,7 +4182,7 @@ XhcConfigHubContext (
XHC_GENERIC_TIMEOUT,
(TRB_TEMPLATE **)(UINTN)&EvtTrb
);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) || (EvtTrb == NULL)) {
DEBUG ((DEBUG_ERROR, "XhcConfigHubContext: Config Endpoint Failed, Status = %r\n", Status));
}
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
index c956e45..158749b 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
@@ -1748,7 +1748,7 @@ XhcPeiSetConfigCmd (
MaxDci = 0;
- IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)ConfigDesc + ConfigDesc->Length);
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
@@ -1759,7 +1759,7 @@ XhcPeiSetConfigCmd (
MaxDci = 1;
}
- EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
@@ -1974,7 +1974,7 @@ XhcPeiSetConfigCmd64 (
MaxDci = 0;
- IfDesc = (USB_INTERFACE_DESCRIPTOR *)(ConfigDesc + 1);
+ IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)ConfigDesc + ConfigDesc->Length);
for (Index = 0; Index < ConfigDesc->NumInterfaces; Index++) {
while ((IfDesc->DescriptorType != USB_DESC_TYPE_INTERFACE) || (IfDesc->AlternateSetting != 0)) {
IfDesc = (USB_INTERFACE_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
@@ -1985,7 +1985,7 @@ XhcPeiSetConfigCmd64 (
MaxDci = 1;
}
- EpDesc = (USB_ENDPOINT_DESCRIPTOR *)(IfDesc + 1);
+ EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)IfDesc + IfDesc->Length);
for (EpIndex = 0; EpIndex < NumEp; EpIndex++) {
while (EpDesc->DescriptorType != USB_DESC_TYPE_ENDPOINT) {
EpDesc = (USB_ENDPOINT_DESCRIPTOR *)((UINTN)EpDesc + EpDesc->Length);
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
index b183ca1..61ddbe5 100644
--- a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
@@ -329,8 +329,17 @@ Transaction (
((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);
+ DummyReadBuffer = AllocateZeroPool (WriteBytes);
+ if (DummyReadBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DummyWriteBuffer = AllocateZeroPool (ReadBytes);
+ if (DummyWriteBuffer == NULL) {
+ FreePool (DummyReadBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
SpiChip->BusTransaction.ReadBuffer = DummyReadBuffer;
SpiChip->BusTransaction.ReadBytes = WriteBytes;
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
index cd0a2c9..a38db47 100644
--- a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
@@ -59,8 +59,7 @@ SpiBusEntry (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n"));
- Status = EFI_NOT_FOUND;
- goto Exit;
+ return EFI_NOT_FOUND;
}
// Locate the SPI Configuration Protocol
@@ -108,7 +107,7 @@ SpiBusEntry (
// Get SpiHc from the SpiHcHandles
Status = gBS->HandleProtocol (
SpiHcHandles[HcIndex],
- &gEfiDevicePathProtocolGuid,
+ &gEfiSpiHcProtocolGuid,
(VOID **)&SpiHc
);
@@ -193,6 +192,9 @@ SpiBusEntry (
}
Exit:
+
+ gBS->FreePool (SpiHcHandles);
+
DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status = %r)\n", __func__, Status));
return Status;
}
diff --git a/MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.c b/MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.c
index 3ac5420..ae8abda 100644
--- a/MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.c
+++ b/MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlash.c
@@ -48,11 +48,22 @@ FillWriteBuffer (
UINT32 Index;
UINT8 SfdpAddressBytes;
- SfdpAddressBytes = (UINT8)Instance->SfdpBasicFlash->AddressBytes;
+ if ((Instance == NULL) || ((WriteBytes != 0) && (WriteBuffer == NULL))) {
+ ASSERT (Instance != NULL);
+ ASSERT (WriteBytes == 0 || WriteBuffer != NULL);
+ return 0;
+ }
+
+ if (Instance->SfdpBasicFlash == NULL) {
+ SfdpAddressBytes = 0;
+ } else {
+ SfdpAddressBytes = (UINT8)Instance->SfdpBasicFlash->AddressBytes;
+ }
// Copy Opcode into Write Buffer
Instance->SpiTransactionWriteBuffer[0] = Opcode;
Index = 1;
+ AddressSize = 0;
if (UseAddress) {
if (AddressBytesSupported == SPI_ADDR_3BYTE_ONLY) {
if (SfdpAddressBytes != 0) {
diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
index b8651ff..4c7ec64 100644
--- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
+++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -1017,6 +1017,55 @@ UfsEndOfPei (
}
/**
+ Finishes device initialization by setting fDeviceInit flag and waiting until device responds by
+ clearing it.
+
+ @param[in] Private Pointer to the UFS_PEIM_HC_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS The operation succeeds.
+ @retval Others The operation fails.
+
+**/
+EFI_STATUS
+UfsFinishDeviceInitialization (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ UINT8 DeviceInitStatus;
+ UINT32 Timeout;
+
+ DeviceInitStatus = 0xFF;
+ Timeout = PcdGet32 (PcdUfsInitialCompletionTimeout);
+
+ //
+ // The host enables the device initialization completion by setting fDeviceInit flag.
+ //
+ Status = UfsSetFlag (Private, UfsFlagDevInit);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ do {
+ Status = UfsReadFlag (Private, UfsFlagDevInit, &DeviceInitStatus);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MicroSecondDelay (1);
+ Timeout--;
+ } while (DeviceInitStatus != 0 && Timeout != 0);
+
+ if (Timeout == 0) {
+ DEBUG ((DEBUG_ERROR, "%a: DeviceInitStatus = %x EFI_TIMEOUT \n", __func__, DeviceInitStatus));
+ return EFI_TIMEOUT;
+ } else {
+ DEBUG ((DEBUG_INFO, "%a: Timeout left = %x EFI_SUCCESS \n", __func__, Timeout));
+ return EFI_SUCCESS;
+ }
+}
+
+/**
The user code starts with this function.
@param FileHandle Handle of the file being invoked.
@@ -1033,13 +1082,17 @@ InitializeUfsBlockIoPeim (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
- EFI_STATUS Status;
- UFS_PEIM_HC_PRIVATE_DATA *Private;
- EDKII_UFS_HOST_CONTROLLER_PPI *UfsHcPpi;
- UINT32 Index;
- UINTN MmioBase;
- UINT8 Controller;
- UFS_UNIT_DESC UnitDescriptor;
+ EFI_STATUS Status;
+ UFS_PEIM_HC_PRIVATE_DATA *Private;
+ EDKII_UFS_HOST_CONTROLLER_PPI *UfsHcPpi;
+ UINT32 Index;
+ UINTN MmioBase;
+ UINT8 Controller;
+ UFS_UNIT_DESC UnitDescriptor;
+ EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi = NULL;
+ UFS_DEV_DESC DeviceDescriptor;
+ UINT8 RefClkAttr;
+ EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE Attributes;
//
// Shadow this PEIM to run from memory
@@ -1061,6 +1114,19 @@ InitializeUfsBlockIoPeim (
return EFI_DEVICE_ERROR;
}
+ //
+ // Locate ufs host controller platform PPI
+ //
+ Status = PeiServicesLocatePpi (
+ &gEdkiiUfsHcPlatformPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&UfsHcPlatformPpi
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "LocatePpi gEdkiiUfsHcPlatformPpiGuid Status :%r\n", Status));
+ }
+
IoMmuInit ();
Controller = 0;
@@ -1096,7 +1162,7 @@ InitializeUfsBlockIoPeim (
//
// Initialize UFS Host Controller H/W.
//
- Status = UfsControllerInit (Private);
+ Status = UfsControllerInit (UfsHcPlatformPpi, Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "UfsDevicePei: Host Controller Initialization Error, Status = %r\n", Status));
Controller++;
@@ -1116,34 +1182,96 @@ InitializeUfsBlockIoPeim (
}
//
- // The host enables the device initialization completion by setting fDeviceInit flag.
+ // Check the UFS device is initialized completed.
//
- Status = UfsSetFlag (Private, UfsFlagDevInit);
+ Status = UfsFinishDeviceInitialization (Private);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Ufs Set fDeviceInit Flag Error, Status = %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "Device failed to finish initialization, Status = %r\n", Status));
Controller++;
continue;
}
- //
- // Check if 8 common luns are active and set corresponding bit mask.
- //
- for (Index = 0; Index < UFS_PEIM_MAX_LUNS; Index++) {
- Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8)Index, 0, &UnitDescriptor, sizeof (UFS_UNIT_DESC));
+ if ((UfsHcPlatformPpi != NULL) &&
+ ((UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq19p2Mhz) ||
+ (UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq26Mhz) ||
+ (UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq38p4Mhz)))
+ {
+ RefClkAttr = UfsAttrRefClkFreq;
+ Attributes = EdkiiUfsCardRefClkFreqObsolete;
+
+ Status = UfsRwAttributes (Private, TRUE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
+ DEBUG ((DEBUG_INFO, "UfsRwAttributes #1 Status = %r \n", Status));
+ if (!EFI_ERROR (Status)) {
+ if (Attributes != UfsHcPlatformPpi->RefClkFreq) {
+ Attributes = UfsHcPlatformPpi->RefClkFreq;
+ DEBUG (
+ (DEBUG_INFO,
+ "Setting bRefClkFreq attribute(%x) to %x\n 0 -> 19.2 Mhz\n 1 -> 26 Mhz\n 2 -> 38.4 Mhz\n 3 -> Obsolete\n",
+ RefClkAttr,
+ Attributes)
+ );
+ Status = UfsRwAttributes (Private, FALSE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
+ DEBUG ((DEBUG_INFO, "UfsRwAttributes #2 Status = %r \n", Status));
+ if (EFI_ERROR (Status)) {
+ DEBUG (
+ (DEBUG_ERROR,
+ "Failed to Change Reference Clock Attribute to, Status = %r \n",
+ Status)
+ );
+ }
+ }
+ } else {
+ DEBUG (
+ (DEBUG_ERROR,
+ "Failed to Read Reference Clock Attribute, Status = %r \n",
+ Status)
+ );
+ }
+ }
+
+ if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
+ Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPostLinkStartup);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Fail to read UFS Unit Descriptor, Index = %X, Status = %r\n", Index, Status));
+ DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostLinkStartup, Status = %r\n", Status));
+ Controller++;
continue;
}
- if (UnitDescriptor.LunEn == 0x1) {
- DEBUG ((DEBUG_INFO, "Ufs %d Lun %d is enabled\n", Controller, Index));
- Private->Luns.BitMask |= (BIT0 << Index);
+ //
+ // Check if 8 common luns are active and set corresponding bit mask.
+ //
+ for (Index = 0; Index < UFS_PEIM_MAX_LUNS; Index++) {
+ Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8)Index, 0, &UnitDescriptor, sizeof (UFS_UNIT_DESC));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to read UFS Unit Descriptor, Index = %X, Status = %r\n", Index, Status));
+ continue;
+ }
+
+ if (UnitDescriptor.LunEn == 0x1) {
+ DEBUG ((DEBUG_INFO, "Ufs %d Lun %d is enabled\n", Controller, Index));
+ Private->Luns.BitMask |= (BIT0 << Index);
+ }
}
- }
- PeiServicesInstallPpi (&Private->BlkIoPpiList);
- PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
- Controller++;
+ //
+ // Get Ufs Device's Lun Info by reading Configuration Descriptor
+ //
+ Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &DeviceDescriptor, sizeof (UFS_DEV_DESC));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));
+ Controller++;
+ continue;
+ }
+
+ if (DeviceDescriptor.SecurityLun == 0x1) {
+ DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
+ Private->Luns.BitMask |= BIT11;
+ }
+
+ PeiServicesInstallPpi (&Private->BlkIoPpiList);
+ PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
+ Controller++;
+ }
}
return EFI_SUCCESS;
diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h
index ed4776f..97fabaf 100644
--- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h
+++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.h
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -11,6 +11,7 @@
#include <PiPei.h>
#include <Ppi/UfsHostController.h>
+#include <Ppi/UfsHostControllerPlatformPpi.h>
#include <Ppi/BlockIo.h>
#include <Ppi/BlockIo2.h>
#include <Ppi/IoMmu.h>
@@ -22,11 +23,13 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/IoLib.h>
#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
#include <Library/PeiServicesLib.h>
#include <IndustryStandard/Scsi.h>
+#include <IndustryStandard/Ufs.h>
+#include <IndustryStandard/UfsHci.h>
-#include "UfsHci.h"
#include "UfsHcMem.h"
#define UFS_PEIM_HC_SIG SIGNATURE_32 ('U', 'F', 'S', 'H')
@@ -156,6 +159,33 @@ typedef struct _UFS_DEVICE_MANAGEMENT_REQUEST_PACKET {
} UFS_DEVICE_MANAGEMENT_REQUEST_PACKET;
/**
+ Read or write specified attribute of a UFS device.
+
+ @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
+ @param[in] Read The boolean variable to show r/w direction.
+ @param[in] AttrId The ID of Attribute.
+ @param[in] Index The Index of Attribute.
+ @param[in] Selector The Selector of Attribute.
+ @param[in, out] Attributes The value of Attribute to be read or written.
+
+ @retval EFI_SUCCESS The Attribute was read/written successfully.
+ @retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a
+ type of UFS device descriptor.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.
+
+**/
+EFI_STATUS
+UfsRwAttributes (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN BOOLEAN Read,
+ IN UINT8 AttrId,
+ IN UINT8 Index,
+ IN UINT8 Selector,
+ IN OUT UINT32 *Attributes
+ );
+
+/**
Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@@ -192,7 +222,8 @@ UfsExecScsiCmds (
**/
EFI_STATUS
UfsControllerInit (
- IN UFS_PEIM_HC_PRIVATE_DATA *Private
+ IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private
);
/**
@@ -227,6 +258,25 @@ UfsSetFlag (
);
/**
+ Read specified flag from a UFS device.
+
+ @param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
+ @param[in] FlagId The ID of flag to be read.
+ @param[out] Value The flag's value.
+
+ @retval EFI_SUCCESS The flag was read successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.
+
+**/
+EFI_STATUS
+UfsReadFlag (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINT8 FlagId,
+ OUT UINT8 *Value
+ );
+
+/**
Read or write specified device descriptor of a UFS device.
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
index 6e1cbfd..978a2fa 100644
--- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
+++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
@@ -28,7 +28,6 @@
UfsBlockIoPei.c
UfsBlockIoPei.h
UfsHci.c
- UfsHci.h
UfsHcMem.c
UfsHcMem.h
DmaMem.c
@@ -41,6 +40,7 @@
IoLib
TimerLib
BaseMemoryLib
+ PcdLib
PeimEntryPoint
PeiServicesLib
DebugLib
@@ -51,10 +51,13 @@
gEdkiiPeiUfsHostControllerPpiGuid ## CONSUMES
gEdkiiIoMmuPpiGuid ## CONSUMES
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
+ gEdkiiUfsHcPlatformPpiGuid ## SOMETIMES CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUfsInitialCompletionTimeout ## CONSUMES
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid AND gEdkiiPeiUfsHostControllerPpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
UfsBlockIoPeiExtra.uni
-
diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c
index d19a7fe..8879891 100644
--- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c
+++ b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.c
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -552,8 +552,8 @@ UfsCreateDMCommandDesc (
}
if (((Opcode != UtpQueryFuncOpcodeRdFlag) && (Opcode != UtpQueryFuncOpcodeSetFlag) &&
- (Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag)) &&
- ((DataSize == 0) || (Data == NULL)))
+ (Opcode != UtpQueryFuncOpcodeClrFlag) && (Opcode != UtpQueryFuncOpcodeTogFlag) &&
+ (Opcode != UtpQueryFuncOpcodeRdAttr)) && ((DataSize == 0) || (Data == NULL)))
{
return EFI_INVALID_PARAMETER;
}
@@ -759,6 +759,7 @@ UfsGetReturnDataFromQueryResponse (
)
{
UINT16 ReturnDataSize;
+ UINT32 ReturnData;
ReturnDataSize = 0;
@@ -799,6 +800,16 @@ UfsGetReturnDataFromQueryResponse (
//
*((UINT8 *)(Packet->OutDataBuffer)) = *((UINT8 *)&(QueryResp->Tsf.Value) + 3);
break;
+ case UtpQueryFuncOpcodeRdAttr:
+ ReturnData = QueryResp->Tsf.Value;
+ SwapLittleEndianToBigEndian ((UINT8 *)&ReturnData, sizeof (UINT32));
+ CopyMem (Packet->InDataBuffer, &ReturnData, sizeof (UINT32));
+ break;
+ case UtpQueryFuncOpcodeWrAttr:
+ ReturnData = QueryResp->Tsf.Value;
+ SwapLittleEndianToBigEndian ((UINT8 *)&ReturnData, sizeof (UINT32));
+ CopyMem (Packet->OutDataBuffer, &ReturnData, sizeof (UINT32));
+ break;
default:
return EFI_INVALID_PARAMETER;
}
@@ -833,7 +844,9 @@ UfsSendDmRequestRetry (
UINT8 *CmdDescBase;
UINT32 CmdDescSize;
- //
+ // Workaround: Adding this one second for reading descriptor
+ MicroSecondDelay (1 * 1000 * 1000); // delay 1 seconds
+
// Find out which slot of transfer request list is available.
//
Status = UfsFindAvailableSlotInTrl (Private, &Slot);
@@ -981,6 +994,56 @@ UfsRwDeviceDesc (
}
/**
+ Read or write specified attribute of a UFS device.
+
+ @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
+ @param[in] Read The boolean variable to show r/w direction.
+ @param[in] AttrId The ID of Attribute.
+ @param[in] Index The Index of Attribute.
+ @param[in] Selector The Selector of Attribute.
+ @param[in, out] Attributes The value of Attribute to be read or written.
+
+ @retval EFI_SUCCESS The Attribute was read/written successfully.
+ @retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a
+ type of UFS device descriptor.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.
+
+**/
+EFI_STATUS
+UfsRwAttributes (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN BOOLEAN Read,
+ IN UINT8 AttrId,
+ IN UINT8 Index,
+ IN UINT8 Selector,
+ IN OUT UINT32 *Attributes
+ )
+{
+ UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;
+
+ ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));
+
+ if (Read) {
+ Packet.DataDirection = UfsDataIn;
+ Packet.Opcode = UtpQueryFuncOpcodeRdAttr;
+ Packet.InDataBuffer = Attributes;
+ } else {
+ Packet.DataDirection = UfsDataOut;
+ Packet.Opcode = UtpQueryFuncOpcodeWrAttr;
+ Packet.OutDataBuffer = Attributes;
+ Packet.OutTransferLength = sizeof (UINT32);
+ }
+
+ Packet.DescId = AttrId;
+ Packet.Index = Index;
+ Packet.Selector = Selector;
+ Packet.Timeout = UFS_TIMEOUT;
+
+ return UfsSendDmRequest (Private, &Packet);
+}
+
+/**
Read or write specified flag of a UFS device.
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@@ -1066,6 +1129,32 @@ UfsSetFlag (
}
/**
+ Read specified flag from a UFS device.
+
+ @param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
+ @param[in] FlagId The ID of flag to be read.
+ @param[out] Value The flag's value.
+
+ @retval EFI_SUCCESS The flag was read successfully.
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to read the flag.
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of reading the flag.
+
+**/
+EFI_STATUS
+UfsReadFlag (
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private,
+ IN UINT8 FlagId,
+ OUT UINT8 *Value
+ )
+{
+ EFI_STATUS Status;
+
+ Status = UfsRwFlags (Private, TRUE, FlagId, Value);
+
+ return Status;
+}
+
+/**
Sends NOP IN cmd to a UFS device for initialization process request.
For more details, please refer to UFS 2.0 spec Figure 13.3.
@@ -1361,6 +1450,7 @@ UfsExecUicCommands (
/**
Enable the UFS host controller for accessing.
+ @param[in] UfsHcPlatformPpi The pointer to the EDKII_UFS_HC_PLATFORM_PPI data structure
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@retval EFI_SUCCESS The UFS host controller enabling was executed successfully.
@@ -1369,13 +1459,22 @@ UfsExecUicCommands (
**/
EFI_STATUS
UfsEnableHostController (
- IN UFS_PEIM_HC_PRIVATE_DATA *Private
+ IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
UINTN Address;
UINT32 Data;
+ if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
+ Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPreHce);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreHce, Status = %r\n", Status));
+ return Status;
+ }
+ }
+
//
// UFS 2.0 spec section 7.1.1 - Host Controller Initialization
//
@@ -1409,6 +1508,14 @@ UfsEnableHostController (
return EFI_DEVICE_ERROR;
}
+ if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
+ Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPostHce);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostHce, Status = %r\n", Status));
+ return Status;
+ }
+ }
+
return EFI_SUCCESS;
}
@@ -1424,7 +1531,8 @@ UfsEnableHostController (
**/
EFI_STATUS
UfsDeviceDetection (
- IN UFS_PEIM_HC_PRIVATE_DATA *Private
+ IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private
)
{
UINTN Retry;
@@ -1432,6 +1540,14 @@ UfsDeviceDetection (
UINT32 Data;
EFI_STATUS Status;
+ if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
+ Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPreLinkStartup);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPreLinkStartup, Status = %r\n", Status));
+ return Status;
+ }
+ }
+
//
// Start UFS device detection.
// Try up to 3 times for establishing data link with device.
@@ -1599,6 +1715,7 @@ UfsInitTransferRequestList (
/**
Initialize the UFS host controller.
+ @param[in] UfsHcPlatformPpi The pointer to the EDKII_UFS_HC_PLATFORM_PPI data structure. // APTIOV_OVERRIDE
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
@retval EFI_SUCCESS The Ufs Host Controller is initialized successfully.
@@ -1607,18 +1724,19 @@ UfsInitTransferRequestList (
**/
EFI_STATUS
UfsControllerInit (
- IN UFS_PEIM_HC_PRIVATE_DATA *Private
+ IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi,
+ IN UFS_PEIM_HC_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
- Status = UfsEnableHostController (Private);
+ Status = UfsEnableHostController (UfsHcPlatformPpi, Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "UfsDevicePei: Enable Host Controller Fails, Status = %r\n", Status));
return Status;
}
- Status = UfsDeviceDetection (Private);
+ Status = UfsDeviceDetection (UfsHcPlatformPpi, Private);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "UfsDevicePei: Device Detection Fails, Status = %r\n", Status));
return Status;
diff --git a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.h b/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.h
deleted file mode 100644
index f19b653..0000000
--- a/MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsHci.h
+++ /dev/null
@@ -1,1336 +0,0 @@
-/** @file
- UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface
- for upper layer application to execute UFS-supported SCSI cmds.
-
- Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _UFS_PASS_THRU_HCI_H_
-#define _UFS_PASS_THRU_HCI_H_
-
-//
-// Host Capabilities Register Offsets
-//
-#define UFS_HC_CAP_OFFSET 0x0000 // Controller Capabilities
-#define UFS_HC_VER_OFFSET 0x0008 // Version
-#define UFS_HC_DDID_OFFSET 0x0010 // Device ID and Device Class
-#define UFS_HC_PMID_OFFSET 0x0014 // Product ID and Manufacturer ID
-#define UFS_HC_AHIT_OFFSET 0x0018 // Auto-Hibernate Idle Timer
-//
-// Operation and Runtime Register Offsets
-//
-#define UFS_HC_IS_OFFSET 0x0020 // Interrupt Status
-#define UFS_HC_IE_OFFSET 0x0024 // Interrupt Enable
-#define UFS_HC_STATUS_OFFSET 0x0030 // Host Controller Status
-#define UFS_HC_ENABLE_OFFSET 0x0034 // Host Controller Enable
-#define UFS_HC_UECPA_OFFSET 0x0038 // Host UIC Error Code PHY Adapter Layer
-#define UFS_HC_UECDL_OFFSET 0x003c // Host UIC Error Code Data Link Layer
-#define UFS_HC_UECN_OFFSET 0x0040 // Host UIC Error Code Network Layer
-#define UFS_HC_UECT_OFFSET 0x0044 // Host UIC Error Code Transport Layer
-#define UFS_HC_UECDME_OFFSET 0x0048 // Host UIC Error Code DME
-#define UFS_HC_UTRIACR_OFFSET 0x004c // UTP Transfer Request Interrupt Aggregation Control Register
-//
-// UTP Transfer Register Offsets
-//
-#define UFS_HC_UTRLBA_OFFSET 0x0050 // UTP Transfer Request List Base Address
-#define UFS_HC_UTRLBAU_OFFSET 0x0054 // UTP Transfer Request List Base Address Upper 32-Bits
-#define UFS_HC_UTRLDBR_OFFSET 0x0058 // UTP Transfer Request List Door Bell Register
-#define UFS_HC_UTRLCLR_OFFSET 0x005c // UTP Transfer Request List CLear Register
-#define UFS_HC_UTRLRSR_OFFSET 0x0060 // UTP Transfer Request Run-Stop Register
-//
-// UTP Task Management Register Offsets
-//
-#define UFS_HC_UTMRLBA_OFFSET 0x0070 // UTP Task Management Request List Base Address
-#define UFS_HC_UTMRLBAU_OFFSET 0x0074 // UTP Task Management Request List Base Address Upper 32-Bits
-#define UFS_HC_UTMRLDBR_OFFSET 0x0078 // UTP Task Management Request List Door Bell Register
-#define UFS_HC_UTMRLCLR_OFFSET 0x007c // UTP Task Management Request List CLear Register
-#define UFS_HC_UTMRLRSR_OFFSET 0x0080 // UTP Task Management Run-Stop Register
-//
-// UIC Command Register Offsets
-//
-#define UFS_HC_UIC_CMD_OFFSET 0x0090 // UIC Command Register
-#define UFS_HC_UCMD_ARG1_OFFSET 0x0094 // UIC Command Argument 1
-#define UFS_HC_UCMD_ARG2_OFFSET 0x0098 // UIC Command Argument 2
-#define UFS_HC_UCMD_ARG3_OFFSET 0x009c // UIC Command Argument 3
-//
-// UMA Register Offsets
-//
-#define UFS_HC_UMA_OFFSET 0x00b0 // Reserved for Unified Memory Extension
-
-#define UFS_HC_HCE_EN BIT0
-#define UFS_HC_HCS_DP BIT0
-#define UFS_HC_HCS_UCRDY BIT3
-#define UFS_HC_IS_ULSS BIT8
-#define UFS_HC_IS_UCCS BIT10
-#define UFS_HC_CAP_64ADDR BIT24
-#define UFS_HC_CAP_NUTMRS (BIT16 | BIT17 | BIT18)
-#define UFS_HC_CAP_NUTRS (BIT0 | BIT1 | BIT2 | BIT3 | BIT4)
-#define UFS_HC_UTMRLRSR BIT0
-#define UFS_HC_UTRLRSR BIT0
-
-//
-// The initial value of the OCS field of UTP TRD or TMRD descriptor
-// defined in JEDEC JESD223 specification
-//
-#define UFS_HC_TRD_OCS_INIT_VALUE 0x0F
-
-//
-// A maximum of length of 256KB is supported by PRDT entry
-//
-#define UFS_MAX_DATA_LEN_PER_PRD 0x40000
-
-#define UFS_STORAGE_COMMAND_TYPE 0x01
-
-#define UFS_REGULAR_COMMAND 0x00
-#define UFS_INTERRUPT_COMMAND 0x01
-
-#define UFS_LUN_0 0x00
-#define UFS_LUN_1 0x01
-#define UFS_LUN_2 0x02
-#define UFS_LUN_3 0x03
-#define UFS_LUN_4 0x04
-#define UFS_LUN_5 0x05
-#define UFS_LUN_6 0x06
-#define UFS_LUN_7 0x07
-#define UFS_WLUN_REPORT_LUNS 0x81
-#define UFS_WLUN_UFS_DEV 0xD0
-#define UFS_WLUN_BOOT 0xB0
-#define UFS_WLUN_RPMB 0xC4
-
-#pragma pack(1)
-
-//
-// UFSHCI 2.0 Spec Section 5.2.1 Offset 00h: CAP - Controller Capabilities
-//
-typedef struct {
- UINT8 Nutrs : 4; // Number of UTP Transfer Request Slots
- UINT8 Rsvd1 : 4;
-
- UINT8 NoRtt; // Number of outstanding READY TO TRANSFER (RTT) requests supported
-
- UINT8 Nutmrs : 3; // Number of UTP Task Management Request Slots
- UINT8 Rsvd2 : 4;
- UINT8 AutoHs : 1; // Auto-Hibernation Support
-
- UINT8 As64 : 1; // 64-bit addressing supported
- UINT8 Oodds : 1; // Out of order data delivery supported
- UINT8 UicDmetms : 1; // UIC DME_TEST_MODE command supported
- UINT8 Ume : 1; // Reserved for Unified Memory Extension
- UINT8 Rsvd4 : 4;
-} UFS_HC_CAP;
-
-//
-// UFSHCI 2.0 Spec Section 5.2.2 Offset 08h: VER - UFS Version
-//
-typedef struct {
- UINT8 Vs : 4; // Version Suffix
- UINT8 Mnr : 4; // Minor version number
-
- UINT8 Mjr; // Major version number
-
- UINT16 Rsvd1;
-} UFS_HC_VER;
-
-//
-// UFSHCI 2.0 Spec Section 5.2.3 Offset 10h: HCPID - Host Controller Product ID
-//
-#define UFS_HC_PID UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.2.4 Offset 14h: HCMID - Host Controller Manufacturer ID
-//
-#define UFS_HC_MID UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.2.5 Offset 18h: AHIT - Auto-Hibernate Idle Timer
-//
-typedef struct {
- UINT32 Ahitv : 10; // Auto-Hibernate Idle Timer Value
- UINT32 Ts : 3; // Timer scale
- UINT32 Rsvd1 : 19;
-} UFS_HC_AHIT;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.1 Offset 20h: IS - Interrupt Status
-//
-typedef struct {
- UINT16 Utrcs : 1; // UTP Transfer Request Completion Status
- UINT16 Udepri : 1; // UIC DME_ENDPOINT_RESET Indication
- UINT16 Ue : 1; // UIC Error
- UINT16 Utms : 1; // UIC Test Mode Status
-
- UINT16 Upms : 1; // UIC Power Mode Status
- UINT16 Uhxs : 1; // UIC Hibernate Exit Status
- UINT16 Uhes : 1; // UIC Hibernate Enter Status
- UINT16 Ulls : 1; // UIC Link Lost Status
-
- UINT16 Ulss : 1; // UIC Link Startup Status
- UINT16 Utmrcs : 1; // UTP Task Management Request Completion Status
- UINT16 Uccs : 1; // UIC Command Completion Status
- UINT16 Dfes : 1; // Device Fatal Error Status
-
- UINT16 Utpes : 1; // UTP Error Status
- UINT16 Rsvd1 : 3;
-
- UINT16 Hcfes : 1; // Host Controller Fatal Error Status
- UINT16 Sbfes : 1; // System Bus Fatal Error Status
- UINT16 Rsvd2 : 14;
-} UFS_HC_IS;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.2 Offset 24h: IE - Interrupt Enable
-//
-typedef struct {
- UINT16 Utrce : 1; // UTP Transfer Request Completion Enable
- UINT16 Udeprie : 1; // UIC DME_ENDPOINT_RESET Enable
- UINT16 Uee : 1; // UIC Error Enable
- UINT16 Utmse : 1; // UIC Test Mode Status Enable
-
- UINT16 Upmse : 1; // UIC Power Mode Status Enable
- UINT16 Uhxse : 1; // UIC Hibernate Exit Status Enable
- UINT16 Uhese : 1; // UIC Hibernate Enter Status Enable
- UINT16 Ullse : 1; // UIC Link Lost Status Enable
-
- UINT16 Ulsse : 1; // UIC Link Startup Status Enable
- UINT16 Utmrce : 1; // UTP Task Management Request Completion Enable
- UINT16 Ucce : 1; // UIC Command Completion Enable
- UINT16 Dfee : 1; // Device Fatal Error Enable
-
- UINT16 Utpee : 1; // UTP Error Enable
- UINT16 Rsvd1 : 3;
-
- UINT16 Hcfee : 1; // Host Controller Fatal Error Enable
- UINT16 Sbfee : 1; // System Bus Fatal Error Enable
- UINT16 Rsvd2 : 14;
-} UFS_HC_IE;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.3 Offset 30h: HCS - Host Controller Status
-//
-typedef struct {
- UINT8 Dp : 1; // Device Present
- UINT8 UtrlRdy : 1; // UTP Transfer Request List Ready
- UINT8 UtmrlRdy : 1; // UTP Task Management Request List Ready
- UINT8 UcRdy : 1; // UIC COMMAND Ready
- UINT8 Rsvd1 : 4;
-
- UINT8 Upmcrs : 3; // UIC Power Mode Change Request Status
- UINT8 Rsvd2 : 1; // UIC Hibernate Exit Status Enable
- UINT8 Utpec : 4; // UTP Error Code
-
- UINT8 TtagUtpE; // Task Tag of UTP error
- UINT8 TlunUtpE; // Target LUN of UTP error
-} UFS_HC_STATUS;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.4 Offset 34h: HCE - Host Controller Enable
-//
-typedef struct {
- UINT32 Hce : 1; // Host Controller Enable
- UINT32 Rsvd1 : 31;
-} UFS_HC_ENABLE;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.5 Offset 38h: UECPA - Host UIC Error Code PHY Adapter Layer
-//
-typedef struct {
- UINT32 Ec : 5; // UIC PHY Adapter Layer Error Code
- UINT32 Rsvd1 : 26;
- UINT32 Err : 1; // UIC PHY Adapter Layer Error
-} UFS_HC_UECPA;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.6 Offset 3ch: UECDL - Host UIC Error Code Data Link Layer
-//
-typedef struct {
- UINT32 Ec : 15; // UIC Data Link Layer Error Code
- UINT32 Rsvd1 : 16;
- UINT32 Err : 1; // UIC Data Link Layer Error
-} UFS_HC_UECDL;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.7 Offset 40h: UECN - Host UIC Error Code Network Layer
-//
-typedef struct {
- UINT32 Ec : 3; // UIC Network Layer Error Code
- UINT32 Rsvd1 : 28;
- UINT32 Err : 1; // UIC Network Layer Error
-} UFS_HC_UECN;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.8 Offset 44h: UECT - Host UIC Error Code Transport Layer
-//
-typedef struct {
- UINT32 Ec : 7; // UIC Transport Layer Error Code
- UINT32 Rsvd1 : 24;
- UINT32 Err : 1; // UIC Transport Layer Error
-} UFS_HC_UECT;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.9 Offset 48h: UECDME - Host UIC Error Code
-//
-typedef struct {
- UINT32 Ec : 1; // UIC DME Error Code
- UINT32 Rsvd1 : 30;
- UINT32 Err : 1; // UIC DME Error
-} UFS_HC_UECDME;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.10 Offset 4Ch: UTRIACR - UTP Transfer Request Interrupt Aggregation Control Register
-//
-typedef struct {
- UINT8 IaToVal; // Interrupt aggregation timeout value
-
- UINT8 IacTh : 5; // Interrupt aggregation counter threshold
- UINT8 Rsvd1 : 3;
-
- UINT8 Ctr : 1; // Counter and Timer Reset
- UINT8 Rsvd2 : 3;
- UINT8 Iasb : 1; // Interrupt aggregation status bit
- UINT8 Rsvd3 : 3;
-
- UINT8 IapwEn : 1; // Interrupt aggregation parameter write enable
- UINT8 Rsvd4 : 6;
- UINT8 IaEn : 1; // Interrupt Aggregation Enable/Disable
-} UFS_HC_UTRIACR;
-
-//
-// UFSHCI 2.0 Spec Section 5.4.1 Offset 50h: UTRLBA - UTP Transfer Request List Base Address
-//
-typedef struct {
- UINT32 Rsvd1 : 10;
- UINT32 UtrlBa : 22; // UTP Transfer Request List Base Address
-} UFS_HC_UTRLBA;
-
-//
-// UFSHCI 2.0 Spec Section 5.4.2 Offset 54h: UTRLBAU - UTP Transfer Request List Base Address Upper 32-bits
-//
-#define UFS_HC_UTRLBAU UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.4.3 Offset 58h: UTRLDBR - UTP Transfer Request List Door Bell Register
-//
-#define UFS_HC_UTRLDBR UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.4.4 Offset 5Ch: UTRLCLR - UTP Transfer Request List CLear Register
-//
-#define UFS_HC_UTRLCLR UINT32
-
-#if 0
-//
-// UFSHCI 2.0 Spec Section 5.4.5 Offset 60h: UTRLRSR - UTP Transfer Request List Run Stop Register
-//
-typedef struct {
- UINT32 UtrlRsr : 1; // UTP Transfer Request List Run-Stop Register
- UINT32 Rsvd1 : 31;
-} UFS_HC_UTRLRSR;
-#endif
-
-//
-// UFSHCI 2.0 Spec Section 5.5.1 Offset 70h: UTMRLBA - UTP Task Management Request List Base Address
-//
-typedef struct {
- UINT32 Rsvd1 : 10;
- UINT32 UtmrlBa : 22; // UTP Task Management Request List Base Address
-} UFS_HC_UTMRLBA;
-
-//
-// UFSHCI 2.0 Spec Section 5.5.2 Offset 74h: UTMRLBAU - UTP Task Management Request List Base Address Upper 32-bits
-//
-#define UFS_HC_UTMRLBAU UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.5.3 Offset 78h: UTMRLDBR - UTP Task Management Request List Door Bell Register
-//
-typedef struct {
- UINT32 UtmrlDbr : 8; // UTP Task Management Request List Door bell Register
- UINT32 Rsvd1 : 24;
-} UFS_HC_UTMRLDBR;
-
-//
-// UFSHCI 2.0 Spec Section 5.5.4 Offset 7Ch: UTMRLCLR - UTP Task Management Request List CLear Register
-//
-typedef struct {
- UINT32 UtmrlClr : 8; // UTP Task Management List Clear Register
- UINT32 Rsvd1 : 24;
-} UFS_HC_UTMRLCLR;
-
-#if 0
-//
-// UFSHCI 2.0 Spec Section 5.5.5 Offset 80h: UTMRLRSR - UTP Task Management Request List Run Stop Register
-//
-typedef struct {
- UINT32 UtmrlRsr : 1; // UTP Task Management Request List Run-Stop Register
- UINT32 Rsvd1 : 31;
-} UFS_HC_UTMRLRSR;
-#endif
-
-//
-// UFSHCI 2.0 Spec Section 5.6.1 Offset 90h: UICCMD - UIC Command
-//
-typedef struct {
- UINT32 CmdOp : 8; // Command Opcode
- UINT32 Rsvd1 : 24;
-} UFS_HC_UICCMD;
-
-//
-// UFSHCI 2.0 Spec Section 5.6.2 Offset 94h: UICCMDARG1 - UIC Command Argument 1
-//
-#define UFS_HC_UICCMD_ARG1 UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.6.2 Offset 98h: UICCMDARG2 - UIC Command Argument 2
-//
-#define UFS_HC_UICCMD_ARG2 UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.6.2 Offset 9ch: UICCMDARG3 - UIC Command Argument 3
-//
-#define UFS_HC_UICCMD_ARG3 UINT32
-
-//
-// UIC command opcodes
-//
-typedef enum {
- UfsUicDmeGet = 0x01,
- UfsUicDmeSet = 0x02,
- UfsUicDmePeerGet = 0x03,
- UfsUicDmePeerSet = 0x04,
- UfsUicDmePwrOn = 0x10,
- UfsUicDmePwrOff = 0x11,
- UfsUicDmeEnable = 0x12,
- UfsUicDmeReset = 0x14,
- UfsUicDmeEndpointReset = 0x15,
- UfsUicDmeLinkStartup = 0x16,
- UfsUicDmeHibernateEnter = 0x17,
- UfsUicDmeHibernateExit = 0x18,
- UfsUicDmeTestMode = 0x1A
-} UFS_UIC_OPCODE;
-
-//
-// UTP Transfer Request Descriptor
-//
-typedef struct {
- //
- // DW0
- //
- UINT32 Rsvd1 : 24;
- UINT32 Int : 1; /* Interrupt */
- UINT32 Dd : 2; /* Data Direction */
- UINT32 Rsvd2 : 1;
- UINT32 Ct : 4; /* Command Type */
-
- //
- // DW1
- //
- UINT32 Rsvd3;
-
- //
- // DW2
- //
- UINT32 Ocs : 8; /* Overall Command Status */
- UINT32 Rsvd4 : 24;
-
- //
- // DW3
- //
- UINT32 Rsvd5;
-
- //
- // DW4
- //
- UINT32 Rsvd6 : 7;
- UINT32 UcdBa : 25; /* UTP Command Descriptor Base Address */
-
- //
- // DW5
- //
- UINT32 UcdBaU; /* UTP Command Descriptor Base Address Upper 32-bits */
-
- //
- // DW6
- //
- UINT16 RuL; /* Response UPIU Length */
- UINT16 RuO; /* Response UPIU Offset */
-
- //
- // DW7
- //
- UINT16 PrdtL; /* PRDT Length */
- UINT16 PrdtO; /* PRDT Offset */
-} UTP_TRD;
-
-typedef struct {
- //
- // DW0
- //
- UINT32 Rsvd1 : 2;
- UINT32 DbAddr : 30; /* Data Base Address */
-
- //
- // DW1
- //
- UINT32 DbAddrU; /* Data Base Address Upper 32-bits */
-
- //
- // DW2
- //
- UINT32 Rsvd2;
-
- //
- // DW3
- //
- UINT32 DbCount : 18; /* Data Byte Count */
- UINT32 Rsvd3 : 14;
-} UTP_TR_PRD;
-
-//
-// UFS 2.0 Spec Section 10.5.3 - UTP Command UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x01*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 CmdSet : 4; /* Command Set Type */
- UINT8 Rsvd1 : 4;
- UINT8 Rsvd2;
- UINT8 Rsvd3;
- UINT8 Rsvd4;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd5;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 ExpDataTranLen; /* Expected Data Transfer Length - Big Endian */
-
- //
- // DW4 - DW7
- //
- UINT8 Cdb[16];
-} UTP_COMMAND_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.4 - UTP Response UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x21*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 CmdSet : 4; /* Command Set Type */
- UINT8 Rsvd1 : 4;
- UINT8 Rsvd2;
- UINT8 Response; /* Response */
- UINT8 Status; /* Status */
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3
- //
- UINT32 ResTranCount; /* Residual Transfer Count - Big Endian */
-
- //
- // DW4 - DW7
- //
- UINT8 Rsvd3[16];
-
- //
- // Data Segment - Sense Data
- //
- UINT16 SenseDataLen; /* Sense Data Length - Big Endian */
- UINT8 SenseData[18]; /* Sense Data */
-} UTP_RESPONSE_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.5 - UTP Data-Out UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x02*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd2;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3
- //
- UINT32 DataBufOffset; /* Data Buffer Offset - Big Endian */
-
- //
- // DW4
- //
- UINT32 DataTranCount; /* Data Transfer Count - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd3[12];
-
- //
- // Data Segment - Data to be sent out
- //
- // UINT8 Data[]; /* Data to be sent out, maximum is 65535 bytes */
-} UTP_DATA_OUT_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.6 - UTP Data-In UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x22*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd2;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3
- //
- UINT32 DataBufOffset; /* Data Buffer Offset - Big Endian */
-
- //
- // DW4
- //
- UINT32 DataTranCount; /* Data Transfer Count - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd3[12];
-
- //
- // Data Segment - Data to be read
- //
- // UINT8 Data[]; /* Data to be read, maximum is 65535 bytes */
-} UTP_DATA_IN_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.7 - UTP Ready-To-Transfer UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x31*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd2;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 DataBufOffset; /* Data Buffer Offset - Big Endian */
-
- //
- // DW4
- //
- UINT32 DataTranCount; /* Data Transfer Count - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd3[12];
-
- //
- // Data Segment - Data to be read
- //
- // UINT8 Data[]; /* Data to be read, maximum is 65535 bytes */
-} UTP_RDY_TO_TRAN_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.8 - UTP Task Management Request UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x04*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1;
- UINT8 TskManFunc; /* Task Management Function */
- UINT8 Rsvd2[2];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd3;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 InputParam1; /* Input Parameter 1 - Big Endian */
-
- //
- // DW4
- //
- UINT32 InputParam2; /* Input Parameter 2 - Big Endian */
-
- //
- // DW5
- //
- UINT32 InputParam3; /* Input Parameter 3 - Big Endian */
-
- //
- // DW6 - DW7
- //
- UINT8 Rsvd4[8];
-} UTP_TM_REQ_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.9 - UTP Task Management Response UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x24*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[2];
- UINT8 Resp; /* Response */
- UINT8 Rsvd2;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd3;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 OutputParam1; /* Output Parameter 1 - Big Endian */
-
- //
- // DW4
- //
- UINT32 OutputParam2; /* Output Parameter 2 - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd4[12];
-} UTP_TM_RESP_UPIU;
-
-//
-// UTP Task Management Request Descriptor
-//
-typedef struct {
- //
- // DW0
- //
- UINT32 Rsvd1 : 24;
- UINT32 Int : 1; /* Interrupt */
- UINT32 Rsvd2 : 7;
-
- //
- // DW1
- //
- UINT32 Rsvd3;
-
- //
- // DW2
- //
- UINT32 Ocs : 8; /* Overall Command Status */
- UINT32 Rsvd4 : 24;
-
- //
- // DW3
- //
- UINT32 Rsvd5;
-
- //
- // DW4 - DW11
- //
- UTP_TM_REQ_UPIU TmReq; /* Task Management Request UPIU */
-
- //
- // DW12 - DW19
- //
- UTP_TM_RESP_UPIU TmResp; /* Task Management Response UPIU */
-} UTP_TMRD;
-
-typedef struct {
- UINT8 Opcode;
- UINT8 DescId;
- UINT8 Index;
- UINT8 Selector;
- UINT16 Rsvd1;
- UINT16 Length;
- UINT32 Value;
- UINT32 Rsvd2;
-} UTP_UPIU_TSF;
-
-//
-// UFS 2.0 Spec Section 10.5.10 - UTP Query Request UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x16*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2;
- UINT8 QueryFunc; /* Query Function */
- UINT8 Rsvd3[2];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd4;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3 - 6
- //
- UTP_UPIU_TSF Tsf; /* Transaction Specific Fields */
-
- //
- // DW7
- //
- UINT8 Rsvd5[4];
-
- //
- // Data Segment - Data to be transferred
- //
- // UINT8 Data[]; /* Data to be transferred, maximum is 65535 bytes */
-} UTP_QUERY_REQ_UPIU;
-
-#define QUERY_FUNC_STD_READ_REQ 0x01
-#define QUERY_FUNC_STD_WRITE_REQ 0x81
-
-typedef enum {
- UtpQueryFuncOpcodeNop = 0x00,
- UtpQueryFuncOpcodeRdDesc = 0x01,
- UtpQueryFuncOpcodeWrDesc = 0x02,
- UtpQueryFuncOpcodeRdAttr = 0x03,
- UtpQueryFuncOpcodeWrAttr = 0x04,
- UtpQueryFuncOpcodeRdFlag = 0x05,
- UtpQueryFuncOpcodeSetFlag = 0x06,
- UtpQueryFuncOpcodeClrFlag = 0x07,
- UtpQueryFuncOpcodeTogFlag = 0x08
-} UTP_QUERY_FUNC_OPCODE;
-
-//
-// UFS 2.0 Spec Section 10.5.11 - UTP Query Response UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x36*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2;
- UINT8 QueryFunc; /* Query Function */
- UINT8 QueryResp; /* Query Response */
- UINT8 Rsvd3;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3 - 6
- //
- UTP_UPIU_TSF Tsf; /* Transaction Specific Fields */
-
- //
- // DW7
- //
- UINT8 Rsvd4[4];
-
- //
- // Data Segment - Data to be transferred
- //
- // UINT8 Data[]; /* Data to be transferred, maximum is 65535 bytes */
-} UTP_QUERY_RESP_UPIU;
-
-typedef enum {
- UfsUtpQueryResponseSuccess = 0x00,
- UfsUtpQueryResponseParamNotReadable = 0xF6,
- UfsUtpQueryResponseParamNotWriteable = 0xF7,
- UfsUtpQueryResponseParamAlreadyWritten = 0xF8,
- UfsUtpQueryResponseInvalidLen = 0xF9,
- UfsUtpQueryResponseInvalidVal = 0xFA,
- UfsUtpQueryResponseInvalidSelector = 0xFB,
- UfsUtpQueryResponseInvalidIndex = 0xFC,
- UfsUtpQueryResponseInvalidIdn = 0xFD,
- UfsUtpQueryResponseInvalidOpc = 0xFE,
- UfsUtpQueryResponseGeneralFailure = 0xFF
-} UTP_QUERY_RESP_CODE;
-
-//
-// UFS 2.0 Spec Section 10.5.12 - UTP Reject UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x3F*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[2];
- UINT8 Response; /* Response - 0x01 */
- UINT8 Rsvd2;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information - 0x00 */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT8 HdrSts; /* Basic Header Status */
- UINT8 Rsvd3;
- UINT8 E2ESts; /* End-to-End Status */
- UINT8 Rsvd4;
-
- //
- // DW4 - DW7
- //
- UINT8 Rsvd5[16];
-} UTP_REJ_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.13 - UTP NOP OUT UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x00*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd3;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3 - DW7
- //
- UINT8 Rsvd4[20];
-} UTP_NOP_OUT_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.14 - UTP NOP IN UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x20*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2[2];
- UINT8 Resp; /* Response - 0x00 */
- UINT8 Rsvd3;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information - 0x00 */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3 - DW7
- //
- UINT8 Rsvd4[20];
-} UTP_NOP_IN_UPIU;
-
-//
-// UFS Descriptors
-//
-typedef enum {
- UfsDeviceDesc = 0x00,
- UfsConfigDesc = 0x01,
- UfsUnitDesc = 0x02,
- UfsInterConnDesc = 0x04,
- UfsStringDesc = 0x05,
- UfsGeometryDesc = 0x07,
- UfsPowerDesc = 0x08
-} UFS_DESC_IDN;
-
-//
-// UFS 2.0 Spec Section 14.1.6.2 - Device Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 Device;
- UINT8 DevClass;
- UINT8 DevSubClass;
- UINT8 Protocol;
- UINT8 NumLun;
- UINT8 NumWLun;
- UINT8 BootEn;
- UINT8 DescAccessEn;
- UINT8 InitPowerMode;
- UINT8 HighPriorityLun;
- UINT8 SecureRemovalType;
- UINT8 SecurityLun;
- UINT8 BgOpsTermLat;
- UINT8 InitActiveIccLevel;
- UINT16 SpecVersion;
- UINT16 ManufactureDate;
- UINT8 ManufacturerName;
- UINT8 ProductName;
- UINT8 SerialName;
- UINT8 OemId;
- UINT16 ManufacturerId;
- UINT8 Ud0BaseOffset;
- UINT8 Ud0ConfParamLen;
- UINT8 DevRttCap;
- UINT16 PeriodicRtcUpdate;
- UINT8 Rsvd1[17];
- UINT8 Rsvd2[16];
-} UFS_DEV_DESC;
-
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 Rsvd1;
- UINT8 BootEn;
- UINT8 DescAccessEn;
- UINT8 InitPowerMode;
- UINT8 HighPriorityLun;
- UINT8 SecureRemovalType;
- UINT8 InitActiveIccLevel;
- UINT16 PeriodicRtcUpdate;
- UINT8 Rsvd2[5];
-} UFS_CONFIG_DESC_GEN_HEADER;
-
-typedef struct {
- UINT8 LunEn;
- UINT8 BootLunId;
- UINT8 LunWriteProt;
- UINT8 MemType;
- UINT32 NumAllocUnits;
- UINT8 DataReliability;
- UINT8 LogicBlkSize;
- UINT8 ProvisionType;
- UINT16 CtxCap;
- UINT8 Rsvd1[3];
-} UFS_UNIT_DESC_CONFIG_PARAMS;
-
-//
-// UFS 2.0 Spec Section 14.1.6.3 - Configuration Descriptor
-//
-typedef struct {
- UFS_CONFIG_DESC_GEN_HEADER Header;
- UFS_UNIT_DESC_CONFIG_PARAMS UnitDescConfParams[8];
-} UFS_CONFIG_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.4 - Geometry Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 MediaTech;
- UINT8 Rsvd1;
- UINT64 TotalRawDevCapacity;
- UINT8 Rsvd2;
- UINT32 SegSize;
- UINT8 AllocUnitSize;
- UINT8 MinAddrBlkSize;
- UINT8 OptReadBlkSize;
- UINT8 OptWriteBlkSize;
- UINT8 MaxInBufSize;
- UINT8 MaxOutBufSize;
- UINT8 RpmbRwSize;
- UINT8 Rsvd3;
- UINT8 DataOrder;
- UINT8 MaxCtxIdNum;
- UINT8 SysDataTagUnitSize;
- UINT8 SysDataResUnitSize;
- UINT8 SupSecRemovalTypes;
- UINT16 SupMemTypes;
- UINT32 SysCodeMaxNumAllocUnits;
- UINT16 SupCodeCapAdjFac;
- UINT32 NonPersMaxNumAllocUnits;
- UINT16 NonPersCapAdjFac;
- UINT32 Enhance1MaxNumAllocUnits;
- UINT16 Enhance1CapAdjFac;
- UINT32 Enhance2MaxNumAllocUnits;
- UINT16 Enhance2CapAdjFac;
- UINT32 Enhance3MaxNumAllocUnits;
- UINT16 Enhance3CapAdjFac;
- UINT32 Enhance4MaxNumAllocUnits;
- UINT16 Enhance4CapAdjFac;
-} UFS_GEOMETRY_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.5 - Unit Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 UnitIdx;
- UINT8 LunEn;
- UINT8 BootLunId;
- UINT8 LunWriteProt;
- UINT8 LunQueueDep;
- UINT8 Rsvd1;
- UINT8 MemType;
- UINT8 DataReliability;
- UINT8 LogicBlkSize;
- UINT64 LogicBlkCount;
- UINT32 EraseBlkSize;
- UINT8 ProvisionType;
- UINT64 PhyMemResCount;
- UINT16 CtxCap;
- UINT8 LargeUnitGranularity;
-} UFS_UNIT_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.6 - RPMB Unit Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 UnitIdx;
- UINT8 LunEn;
- UINT8 BootLunId;
- UINT8 LunWriteProt;
- UINT8 LunQueueDep;
- UINT8 Rsvd1;
- UINT8 MemType;
- UINT8 Rsvd2;
- UINT8 LogicBlkSize;
- UINT64 LogicBlkCount;
- UINT32 EraseBlkSize;
- UINT8 ProvisionType;
- UINT64 PhyMemResCount;
- UINT8 Rsvd3[3];
-} UFS_RPMB_UNIT_DESC;
-
-typedef struct {
- UINT16 Value : 10;
- UINT16 Rsvd1 : 4;
- UINT16 Unit : 2;
-} UFS_POWER_PARAM_ELEMENT;
-
-//
-// UFS 2.0 Spec Section 14.1.6.7 - Power Parameter Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UFS_POWER_PARAM_ELEMENT ActiveIccLevelVcc[16];
- UFS_POWER_PARAM_ELEMENT ActiveIccLevelVccQ[16];
- UFS_POWER_PARAM_ELEMENT ActiveIccLevelVccQ2[16];
-} UFS_POWER_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.8 - InterConnect Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT16 UniProVer;
- UINT16 MphyVer;
-} UFS_INTER_CONNECT_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.9 - 14.1.6.12 - String Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- CHAR16 Unicode[126];
-} UFS_STRING_DESC;
-
-//
-// UFS 2.0 Spec Section 14.2 - Flags
-//
-typedef enum {
- UfsFlagDevInit = 0x01,
- UfsFlagPermWpEn = 0x02,
- UfsFlagPowerOnWpEn = 0x03,
- UfsFlagBgOpsEn = 0x04,
- UfsFlagPurgeEn = 0x06,
- UfsFlagPhyResRemoval = 0x08,
- UfsFlagBusyRtc = 0x09,
- UfsFlagPermDisFwUpdate = 0x0B
-} UFS_FLAGS_IDN;
-
-//
-// UFS 2.0 Spec Section 14.2 - Attributes
-//
-typedef enum {
- UfsAttrBootLunEn = 0x00,
- UfsAttrCurPowerMode = 0x02,
- UfsAttrActiveIccLevel = 0x03,
- UfsAttrOutOfOrderDataEn = 0x04,
- UfsAttrBgOpStatus = 0x05,
- UfsAttrPurgeStatus = 0x06,
- UfsAttrMaxDataInSize = 0x07,
- UfsAttrMaxDataOutSize = 0x08,
- UfsAttrDynCapNeeded = 0x09,
- UfsAttrRefClkFreq = 0x0a,
- UfsAttrConfigDescLock = 0x0b,
- UfsAttrMaxNumOfRtt = 0x0c,
- UfsAttrExceptionEvtCtrl = 0x0d,
- UfsAttrExceptionEvtSts = 0x0e,
- UfsAttrSecondsPassed = 0x0f,
- UfsAttrContextConf = 0x10,
- UfsAttrCorrPrgBlkNum = 0x11
-} UFS_ATTR_IDN;
-
-typedef enum {
- UfsNoData = 0,
- UfsDataOut = 1,
- UfsDataIn = 2,
- UfsDdReserved
-} UFS_DATA_DIRECTION;
-
-#pragma pack()
-
-#endif
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
index 880e7d8..816532d 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
@@ -759,6 +759,7 @@ UfsFinishDeviceInitialization (
UINT32 Timeout;
DeviceInitStatus = 0xFF;
+ Timeout = PcdGet32 (PcdUfsInitialCompletionTimeout);
//
// The host enables the device initialization completion by setting fDeviceInit flag.
@@ -768,10 +769,6 @@ UfsFinishDeviceInitialization (
return Status;
}
- //
- // There are cards that can take upto 600ms to clear fDeviceInit flag.
- //
- Timeout = UFS_INIT_COMPLETION_TIMEOUT;
do {
Status = UfsReadFlag (Private, UfsFlagDevInit, &DeviceInitStatus);
if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
index bc1139d..6cba29f 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
@@ -24,9 +24,11 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
#include <Library/TimerLib.h>
-#include "UfsPassThruHci.h"
+#include <IndustryStandard/Ufs.h>
+#include <IndustryStandard/UfsHci.h>
#define UFS_PASS_THRU_SIG SIGNATURE_32 ('U', 'F', 'S', 'P')
@@ -38,9 +40,8 @@
// Lun 10: BOOT
// Lun 11: RPMB
//
-#define UFS_MAX_LUNS 12
-#define UFS_WLUN_PREFIX 0xC1
-#define UFS_INIT_COMPLETION_TIMEOUT 600000
+#define UFS_MAX_LUNS 12
+#define UFS_WLUN_PREFIX 0xC1
typedef struct {
UINT8 Lun[UFS_MAX_LUNS];
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
index 92dc257..428b1a7 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
@@ -33,7 +33,6 @@
UfsPassThru.c
UfsPassThru.h
UfsPassThruHci.c
- UfsPassThruHci.h
[Packages]
MdePkg/MdePkg.dec
@@ -48,6 +47,7 @@
UefiDriverEntryPoint
DebugLib
DevicePathLib
+ PcdLib
TimerLib
[Protocols]
@@ -56,5 +56,8 @@
gEdkiiUfsHostControllerProtocolGuid ## TO_START
gEdkiiUfsHcPlatformProtocolGuid ## SOMETIMES_CONSUMES
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUfsInitialCompletionTimeout ## CONSUMES
+
[UserExtensions.TianoCore."ExtraFiles"]
UfsPassThruExtra.uni
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
index 4a9fa01..a03b2ce 100644
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
+++ b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.c
@@ -1808,7 +1808,7 @@ UfsAllocateAlignCommonBuffer (
if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)))) {
UfsHc->FreeBuffer (
UfsHc,
- EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
+ EFI_SIZE_TO_PAGES (Size),
*CmdDescHost
);
*CmdDescHost = NULL;
@@ -1825,7 +1825,7 @@ UfsAllocateAlignCommonBuffer (
);
UfsHc->FreeBuffer (
UfsHc,
- EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (Size)),
+ EFI_SIZE_TO_PAGES (Size),
*CmdDescHost
);
*CmdDescMapping = NULL;
diff --git a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.h b/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.h
deleted file mode 100644
index f19b653..0000000
--- a/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruHci.h
+++ /dev/null
@@ -1,1336 +0,0 @@
-/** @file
- UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface
- for upper layer application to execute UFS-supported SCSI cmds.
-
- Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _UFS_PASS_THRU_HCI_H_
-#define _UFS_PASS_THRU_HCI_H_
-
-//
-// Host Capabilities Register Offsets
-//
-#define UFS_HC_CAP_OFFSET 0x0000 // Controller Capabilities
-#define UFS_HC_VER_OFFSET 0x0008 // Version
-#define UFS_HC_DDID_OFFSET 0x0010 // Device ID and Device Class
-#define UFS_HC_PMID_OFFSET 0x0014 // Product ID and Manufacturer ID
-#define UFS_HC_AHIT_OFFSET 0x0018 // Auto-Hibernate Idle Timer
-//
-// Operation and Runtime Register Offsets
-//
-#define UFS_HC_IS_OFFSET 0x0020 // Interrupt Status
-#define UFS_HC_IE_OFFSET 0x0024 // Interrupt Enable
-#define UFS_HC_STATUS_OFFSET 0x0030 // Host Controller Status
-#define UFS_HC_ENABLE_OFFSET 0x0034 // Host Controller Enable
-#define UFS_HC_UECPA_OFFSET 0x0038 // Host UIC Error Code PHY Adapter Layer
-#define UFS_HC_UECDL_OFFSET 0x003c // Host UIC Error Code Data Link Layer
-#define UFS_HC_UECN_OFFSET 0x0040 // Host UIC Error Code Network Layer
-#define UFS_HC_UECT_OFFSET 0x0044 // Host UIC Error Code Transport Layer
-#define UFS_HC_UECDME_OFFSET 0x0048 // Host UIC Error Code DME
-#define UFS_HC_UTRIACR_OFFSET 0x004c // UTP Transfer Request Interrupt Aggregation Control Register
-//
-// UTP Transfer Register Offsets
-//
-#define UFS_HC_UTRLBA_OFFSET 0x0050 // UTP Transfer Request List Base Address
-#define UFS_HC_UTRLBAU_OFFSET 0x0054 // UTP Transfer Request List Base Address Upper 32-Bits
-#define UFS_HC_UTRLDBR_OFFSET 0x0058 // UTP Transfer Request List Door Bell Register
-#define UFS_HC_UTRLCLR_OFFSET 0x005c // UTP Transfer Request List CLear Register
-#define UFS_HC_UTRLRSR_OFFSET 0x0060 // UTP Transfer Request Run-Stop Register
-//
-// UTP Task Management Register Offsets
-//
-#define UFS_HC_UTMRLBA_OFFSET 0x0070 // UTP Task Management Request List Base Address
-#define UFS_HC_UTMRLBAU_OFFSET 0x0074 // UTP Task Management Request List Base Address Upper 32-Bits
-#define UFS_HC_UTMRLDBR_OFFSET 0x0078 // UTP Task Management Request List Door Bell Register
-#define UFS_HC_UTMRLCLR_OFFSET 0x007c // UTP Task Management Request List CLear Register
-#define UFS_HC_UTMRLRSR_OFFSET 0x0080 // UTP Task Management Run-Stop Register
-//
-// UIC Command Register Offsets
-//
-#define UFS_HC_UIC_CMD_OFFSET 0x0090 // UIC Command Register
-#define UFS_HC_UCMD_ARG1_OFFSET 0x0094 // UIC Command Argument 1
-#define UFS_HC_UCMD_ARG2_OFFSET 0x0098 // UIC Command Argument 2
-#define UFS_HC_UCMD_ARG3_OFFSET 0x009c // UIC Command Argument 3
-//
-// UMA Register Offsets
-//
-#define UFS_HC_UMA_OFFSET 0x00b0 // Reserved for Unified Memory Extension
-
-#define UFS_HC_HCE_EN BIT0
-#define UFS_HC_HCS_DP BIT0
-#define UFS_HC_HCS_UCRDY BIT3
-#define UFS_HC_IS_ULSS BIT8
-#define UFS_HC_IS_UCCS BIT10
-#define UFS_HC_CAP_64ADDR BIT24
-#define UFS_HC_CAP_NUTMRS (BIT16 | BIT17 | BIT18)
-#define UFS_HC_CAP_NUTRS (BIT0 | BIT1 | BIT2 | BIT3 | BIT4)
-#define UFS_HC_UTMRLRSR BIT0
-#define UFS_HC_UTRLRSR BIT0
-
-//
-// The initial value of the OCS field of UTP TRD or TMRD descriptor
-// defined in JEDEC JESD223 specification
-//
-#define UFS_HC_TRD_OCS_INIT_VALUE 0x0F
-
-//
-// A maximum of length of 256KB is supported by PRDT entry
-//
-#define UFS_MAX_DATA_LEN_PER_PRD 0x40000
-
-#define UFS_STORAGE_COMMAND_TYPE 0x01
-
-#define UFS_REGULAR_COMMAND 0x00
-#define UFS_INTERRUPT_COMMAND 0x01
-
-#define UFS_LUN_0 0x00
-#define UFS_LUN_1 0x01
-#define UFS_LUN_2 0x02
-#define UFS_LUN_3 0x03
-#define UFS_LUN_4 0x04
-#define UFS_LUN_5 0x05
-#define UFS_LUN_6 0x06
-#define UFS_LUN_7 0x07
-#define UFS_WLUN_REPORT_LUNS 0x81
-#define UFS_WLUN_UFS_DEV 0xD0
-#define UFS_WLUN_BOOT 0xB0
-#define UFS_WLUN_RPMB 0xC4
-
-#pragma pack(1)
-
-//
-// UFSHCI 2.0 Spec Section 5.2.1 Offset 00h: CAP - Controller Capabilities
-//
-typedef struct {
- UINT8 Nutrs : 4; // Number of UTP Transfer Request Slots
- UINT8 Rsvd1 : 4;
-
- UINT8 NoRtt; // Number of outstanding READY TO TRANSFER (RTT) requests supported
-
- UINT8 Nutmrs : 3; // Number of UTP Task Management Request Slots
- UINT8 Rsvd2 : 4;
- UINT8 AutoHs : 1; // Auto-Hibernation Support
-
- UINT8 As64 : 1; // 64-bit addressing supported
- UINT8 Oodds : 1; // Out of order data delivery supported
- UINT8 UicDmetms : 1; // UIC DME_TEST_MODE command supported
- UINT8 Ume : 1; // Reserved for Unified Memory Extension
- UINT8 Rsvd4 : 4;
-} UFS_HC_CAP;
-
-//
-// UFSHCI 2.0 Spec Section 5.2.2 Offset 08h: VER - UFS Version
-//
-typedef struct {
- UINT8 Vs : 4; // Version Suffix
- UINT8 Mnr : 4; // Minor version number
-
- UINT8 Mjr; // Major version number
-
- UINT16 Rsvd1;
-} UFS_HC_VER;
-
-//
-// UFSHCI 2.0 Spec Section 5.2.3 Offset 10h: HCPID - Host Controller Product ID
-//
-#define UFS_HC_PID UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.2.4 Offset 14h: HCMID - Host Controller Manufacturer ID
-//
-#define UFS_HC_MID UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.2.5 Offset 18h: AHIT - Auto-Hibernate Idle Timer
-//
-typedef struct {
- UINT32 Ahitv : 10; // Auto-Hibernate Idle Timer Value
- UINT32 Ts : 3; // Timer scale
- UINT32 Rsvd1 : 19;
-} UFS_HC_AHIT;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.1 Offset 20h: IS - Interrupt Status
-//
-typedef struct {
- UINT16 Utrcs : 1; // UTP Transfer Request Completion Status
- UINT16 Udepri : 1; // UIC DME_ENDPOINT_RESET Indication
- UINT16 Ue : 1; // UIC Error
- UINT16 Utms : 1; // UIC Test Mode Status
-
- UINT16 Upms : 1; // UIC Power Mode Status
- UINT16 Uhxs : 1; // UIC Hibernate Exit Status
- UINT16 Uhes : 1; // UIC Hibernate Enter Status
- UINT16 Ulls : 1; // UIC Link Lost Status
-
- UINT16 Ulss : 1; // UIC Link Startup Status
- UINT16 Utmrcs : 1; // UTP Task Management Request Completion Status
- UINT16 Uccs : 1; // UIC Command Completion Status
- UINT16 Dfes : 1; // Device Fatal Error Status
-
- UINT16 Utpes : 1; // UTP Error Status
- UINT16 Rsvd1 : 3;
-
- UINT16 Hcfes : 1; // Host Controller Fatal Error Status
- UINT16 Sbfes : 1; // System Bus Fatal Error Status
- UINT16 Rsvd2 : 14;
-} UFS_HC_IS;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.2 Offset 24h: IE - Interrupt Enable
-//
-typedef struct {
- UINT16 Utrce : 1; // UTP Transfer Request Completion Enable
- UINT16 Udeprie : 1; // UIC DME_ENDPOINT_RESET Enable
- UINT16 Uee : 1; // UIC Error Enable
- UINT16 Utmse : 1; // UIC Test Mode Status Enable
-
- UINT16 Upmse : 1; // UIC Power Mode Status Enable
- UINT16 Uhxse : 1; // UIC Hibernate Exit Status Enable
- UINT16 Uhese : 1; // UIC Hibernate Enter Status Enable
- UINT16 Ullse : 1; // UIC Link Lost Status Enable
-
- UINT16 Ulsse : 1; // UIC Link Startup Status Enable
- UINT16 Utmrce : 1; // UTP Task Management Request Completion Enable
- UINT16 Ucce : 1; // UIC Command Completion Enable
- UINT16 Dfee : 1; // Device Fatal Error Enable
-
- UINT16 Utpee : 1; // UTP Error Enable
- UINT16 Rsvd1 : 3;
-
- UINT16 Hcfee : 1; // Host Controller Fatal Error Enable
- UINT16 Sbfee : 1; // System Bus Fatal Error Enable
- UINT16 Rsvd2 : 14;
-} UFS_HC_IE;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.3 Offset 30h: HCS - Host Controller Status
-//
-typedef struct {
- UINT8 Dp : 1; // Device Present
- UINT8 UtrlRdy : 1; // UTP Transfer Request List Ready
- UINT8 UtmrlRdy : 1; // UTP Task Management Request List Ready
- UINT8 UcRdy : 1; // UIC COMMAND Ready
- UINT8 Rsvd1 : 4;
-
- UINT8 Upmcrs : 3; // UIC Power Mode Change Request Status
- UINT8 Rsvd2 : 1; // UIC Hibernate Exit Status Enable
- UINT8 Utpec : 4; // UTP Error Code
-
- UINT8 TtagUtpE; // Task Tag of UTP error
- UINT8 TlunUtpE; // Target LUN of UTP error
-} UFS_HC_STATUS;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.4 Offset 34h: HCE - Host Controller Enable
-//
-typedef struct {
- UINT32 Hce : 1; // Host Controller Enable
- UINT32 Rsvd1 : 31;
-} UFS_HC_ENABLE;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.5 Offset 38h: UECPA - Host UIC Error Code PHY Adapter Layer
-//
-typedef struct {
- UINT32 Ec : 5; // UIC PHY Adapter Layer Error Code
- UINT32 Rsvd1 : 26;
- UINT32 Err : 1; // UIC PHY Adapter Layer Error
-} UFS_HC_UECPA;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.6 Offset 3ch: UECDL - Host UIC Error Code Data Link Layer
-//
-typedef struct {
- UINT32 Ec : 15; // UIC Data Link Layer Error Code
- UINT32 Rsvd1 : 16;
- UINT32 Err : 1; // UIC Data Link Layer Error
-} UFS_HC_UECDL;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.7 Offset 40h: UECN - Host UIC Error Code Network Layer
-//
-typedef struct {
- UINT32 Ec : 3; // UIC Network Layer Error Code
- UINT32 Rsvd1 : 28;
- UINT32 Err : 1; // UIC Network Layer Error
-} UFS_HC_UECN;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.8 Offset 44h: UECT - Host UIC Error Code Transport Layer
-//
-typedef struct {
- UINT32 Ec : 7; // UIC Transport Layer Error Code
- UINT32 Rsvd1 : 24;
- UINT32 Err : 1; // UIC Transport Layer Error
-} UFS_HC_UECT;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.9 Offset 48h: UECDME - Host UIC Error Code
-//
-typedef struct {
- UINT32 Ec : 1; // UIC DME Error Code
- UINT32 Rsvd1 : 30;
- UINT32 Err : 1; // UIC DME Error
-} UFS_HC_UECDME;
-
-//
-// UFSHCI 2.0 Spec Section 5.3.10 Offset 4Ch: UTRIACR - UTP Transfer Request Interrupt Aggregation Control Register
-//
-typedef struct {
- UINT8 IaToVal; // Interrupt aggregation timeout value
-
- UINT8 IacTh : 5; // Interrupt aggregation counter threshold
- UINT8 Rsvd1 : 3;
-
- UINT8 Ctr : 1; // Counter and Timer Reset
- UINT8 Rsvd2 : 3;
- UINT8 Iasb : 1; // Interrupt aggregation status bit
- UINT8 Rsvd3 : 3;
-
- UINT8 IapwEn : 1; // Interrupt aggregation parameter write enable
- UINT8 Rsvd4 : 6;
- UINT8 IaEn : 1; // Interrupt Aggregation Enable/Disable
-} UFS_HC_UTRIACR;
-
-//
-// UFSHCI 2.0 Spec Section 5.4.1 Offset 50h: UTRLBA - UTP Transfer Request List Base Address
-//
-typedef struct {
- UINT32 Rsvd1 : 10;
- UINT32 UtrlBa : 22; // UTP Transfer Request List Base Address
-} UFS_HC_UTRLBA;
-
-//
-// UFSHCI 2.0 Spec Section 5.4.2 Offset 54h: UTRLBAU - UTP Transfer Request List Base Address Upper 32-bits
-//
-#define UFS_HC_UTRLBAU UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.4.3 Offset 58h: UTRLDBR - UTP Transfer Request List Door Bell Register
-//
-#define UFS_HC_UTRLDBR UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.4.4 Offset 5Ch: UTRLCLR - UTP Transfer Request List CLear Register
-//
-#define UFS_HC_UTRLCLR UINT32
-
-#if 0
-//
-// UFSHCI 2.0 Spec Section 5.4.5 Offset 60h: UTRLRSR - UTP Transfer Request List Run Stop Register
-//
-typedef struct {
- UINT32 UtrlRsr : 1; // UTP Transfer Request List Run-Stop Register
- UINT32 Rsvd1 : 31;
-} UFS_HC_UTRLRSR;
-#endif
-
-//
-// UFSHCI 2.0 Spec Section 5.5.1 Offset 70h: UTMRLBA - UTP Task Management Request List Base Address
-//
-typedef struct {
- UINT32 Rsvd1 : 10;
- UINT32 UtmrlBa : 22; // UTP Task Management Request List Base Address
-} UFS_HC_UTMRLBA;
-
-//
-// UFSHCI 2.0 Spec Section 5.5.2 Offset 74h: UTMRLBAU - UTP Task Management Request List Base Address Upper 32-bits
-//
-#define UFS_HC_UTMRLBAU UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.5.3 Offset 78h: UTMRLDBR - UTP Task Management Request List Door Bell Register
-//
-typedef struct {
- UINT32 UtmrlDbr : 8; // UTP Task Management Request List Door bell Register
- UINT32 Rsvd1 : 24;
-} UFS_HC_UTMRLDBR;
-
-//
-// UFSHCI 2.0 Spec Section 5.5.4 Offset 7Ch: UTMRLCLR - UTP Task Management Request List CLear Register
-//
-typedef struct {
- UINT32 UtmrlClr : 8; // UTP Task Management List Clear Register
- UINT32 Rsvd1 : 24;
-} UFS_HC_UTMRLCLR;
-
-#if 0
-//
-// UFSHCI 2.0 Spec Section 5.5.5 Offset 80h: UTMRLRSR - UTP Task Management Request List Run Stop Register
-//
-typedef struct {
- UINT32 UtmrlRsr : 1; // UTP Task Management Request List Run-Stop Register
- UINT32 Rsvd1 : 31;
-} UFS_HC_UTMRLRSR;
-#endif
-
-//
-// UFSHCI 2.0 Spec Section 5.6.1 Offset 90h: UICCMD - UIC Command
-//
-typedef struct {
- UINT32 CmdOp : 8; // Command Opcode
- UINT32 Rsvd1 : 24;
-} UFS_HC_UICCMD;
-
-//
-// UFSHCI 2.0 Spec Section 5.6.2 Offset 94h: UICCMDARG1 - UIC Command Argument 1
-//
-#define UFS_HC_UICCMD_ARG1 UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.6.2 Offset 98h: UICCMDARG2 - UIC Command Argument 2
-//
-#define UFS_HC_UICCMD_ARG2 UINT32
-
-//
-// UFSHCI 2.0 Spec Section 5.6.2 Offset 9ch: UICCMDARG3 - UIC Command Argument 3
-//
-#define UFS_HC_UICCMD_ARG3 UINT32
-
-//
-// UIC command opcodes
-//
-typedef enum {
- UfsUicDmeGet = 0x01,
- UfsUicDmeSet = 0x02,
- UfsUicDmePeerGet = 0x03,
- UfsUicDmePeerSet = 0x04,
- UfsUicDmePwrOn = 0x10,
- UfsUicDmePwrOff = 0x11,
- UfsUicDmeEnable = 0x12,
- UfsUicDmeReset = 0x14,
- UfsUicDmeEndpointReset = 0x15,
- UfsUicDmeLinkStartup = 0x16,
- UfsUicDmeHibernateEnter = 0x17,
- UfsUicDmeHibernateExit = 0x18,
- UfsUicDmeTestMode = 0x1A
-} UFS_UIC_OPCODE;
-
-//
-// UTP Transfer Request Descriptor
-//
-typedef struct {
- //
- // DW0
- //
- UINT32 Rsvd1 : 24;
- UINT32 Int : 1; /* Interrupt */
- UINT32 Dd : 2; /* Data Direction */
- UINT32 Rsvd2 : 1;
- UINT32 Ct : 4; /* Command Type */
-
- //
- // DW1
- //
- UINT32 Rsvd3;
-
- //
- // DW2
- //
- UINT32 Ocs : 8; /* Overall Command Status */
- UINT32 Rsvd4 : 24;
-
- //
- // DW3
- //
- UINT32 Rsvd5;
-
- //
- // DW4
- //
- UINT32 Rsvd6 : 7;
- UINT32 UcdBa : 25; /* UTP Command Descriptor Base Address */
-
- //
- // DW5
- //
- UINT32 UcdBaU; /* UTP Command Descriptor Base Address Upper 32-bits */
-
- //
- // DW6
- //
- UINT16 RuL; /* Response UPIU Length */
- UINT16 RuO; /* Response UPIU Offset */
-
- //
- // DW7
- //
- UINT16 PrdtL; /* PRDT Length */
- UINT16 PrdtO; /* PRDT Offset */
-} UTP_TRD;
-
-typedef struct {
- //
- // DW0
- //
- UINT32 Rsvd1 : 2;
- UINT32 DbAddr : 30; /* Data Base Address */
-
- //
- // DW1
- //
- UINT32 DbAddrU; /* Data Base Address Upper 32-bits */
-
- //
- // DW2
- //
- UINT32 Rsvd2;
-
- //
- // DW3
- //
- UINT32 DbCount : 18; /* Data Byte Count */
- UINT32 Rsvd3 : 14;
-} UTP_TR_PRD;
-
-//
-// UFS 2.0 Spec Section 10.5.3 - UTP Command UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x01*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 CmdSet : 4; /* Command Set Type */
- UINT8 Rsvd1 : 4;
- UINT8 Rsvd2;
- UINT8 Rsvd3;
- UINT8 Rsvd4;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd5;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 ExpDataTranLen; /* Expected Data Transfer Length - Big Endian */
-
- //
- // DW4 - DW7
- //
- UINT8 Cdb[16];
-} UTP_COMMAND_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.4 - UTP Response UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x21*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 CmdSet : 4; /* Command Set Type */
- UINT8 Rsvd1 : 4;
- UINT8 Rsvd2;
- UINT8 Response; /* Response */
- UINT8 Status; /* Status */
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3
- //
- UINT32 ResTranCount; /* Residual Transfer Count - Big Endian */
-
- //
- // DW4 - DW7
- //
- UINT8 Rsvd3[16];
-
- //
- // Data Segment - Sense Data
- //
- UINT16 SenseDataLen; /* Sense Data Length - Big Endian */
- UINT8 SenseData[18]; /* Sense Data */
-} UTP_RESPONSE_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.5 - UTP Data-Out UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x02*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd2;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3
- //
- UINT32 DataBufOffset; /* Data Buffer Offset - Big Endian */
-
- //
- // DW4
- //
- UINT32 DataTranCount; /* Data Transfer Count - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd3[12];
-
- //
- // Data Segment - Data to be sent out
- //
- // UINT8 Data[]; /* Data to be sent out, maximum is 65535 bytes */
-} UTP_DATA_OUT_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.6 - UTP Data-In UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x22*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd2;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3
- //
- UINT32 DataBufOffset; /* Data Buffer Offset - Big Endian */
-
- //
- // DW4
- //
- UINT32 DataTranCount; /* Data Transfer Count - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd3[12];
-
- //
- // Data Segment - Data to be read
- //
- // UINT8 Data[]; /* Data to be read, maximum is 65535 bytes */
-} UTP_DATA_IN_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.7 - UTP Ready-To-Transfer UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x31*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd2;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 DataBufOffset; /* Data Buffer Offset - Big Endian */
-
- //
- // DW4
- //
- UINT32 DataTranCount; /* Data Transfer Count - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd3[12];
-
- //
- // Data Segment - Data to be read
- //
- // UINT8 Data[]; /* Data to be read, maximum is 65535 bytes */
-} UTP_RDY_TO_TRAN_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.8 - UTP Task Management Request UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x04*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1;
- UINT8 TskManFunc; /* Task Management Function */
- UINT8 Rsvd2[2];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd3;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 InputParam1; /* Input Parameter 1 - Big Endian */
-
- //
- // DW4
- //
- UINT32 InputParam2; /* Input Parameter 2 - Big Endian */
-
- //
- // DW5
- //
- UINT32 InputParam3; /* Input Parameter 3 - Big Endian */
-
- //
- // DW6 - DW7
- //
- UINT8 Rsvd4[8];
-} UTP_TM_REQ_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.9 - UTP Task Management Response UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x24*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[2];
- UINT8 Resp; /* Response */
- UINT8 Rsvd2;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd3;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT32 OutputParam1; /* Output Parameter 1 - Big Endian */
-
- //
- // DW4
- //
- UINT32 OutputParam2; /* Output Parameter 2 - Big Endian */
-
- //
- // DW5 - DW7
- //
- UINT8 Rsvd4[12];
-} UTP_TM_RESP_UPIU;
-
-//
-// UTP Task Management Request Descriptor
-//
-typedef struct {
- //
- // DW0
- //
- UINT32 Rsvd1 : 24;
- UINT32 Int : 1; /* Interrupt */
- UINT32 Rsvd2 : 7;
-
- //
- // DW1
- //
- UINT32 Rsvd3;
-
- //
- // DW2
- //
- UINT32 Ocs : 8; /* Overall Command Status */
- UINT32 Rsvd4 : 24;
-
- //
- // DW3
- //
- UINT32 Rsvd5;
-
- //
- // DW4 - DW11
- //
- UTP_TM_REQ_UPIU TmReq; /* Task Management Request UPIU */
-
- //
- // DW12 - DW19
- //
- UTP_TM_RESP_UPIU TmResp; /* Task Management Response UPIU */
-} UTP_TMRD;
-
-typedef struct {
- UINT8 Opcode;
- UINT8 DescId;
- UINT8 Index;
- UINT8 Selector;
- UINT16 Rsvd1;
- UINT16 Length;
- UINT32 Value;
- UINT32 Rsvd2;
-} UTP_UPIU_TSF;
-
-//
-// UFS 2.0 Spec Section 10.5.10 - UTP Query Request UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x16*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2;
- UINT8 QueryFunc; /* Query Function */
- UINT8 Rsvd3[2];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd4;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3 - 6
- //
- UTP_UPIU_TSF Tsf; /* Transaction Specific Fields */
-
- //
- // DW7
- //
- UINT8 Rsvd5[4];
-
- //
- // Data Segment - Data to be transferred
- //
- // UINT8 Data[]; /* Data to be transferred, maximum is 65535 bytes */
-} UTP_QUERY_REQ_UPIU;
-
-#define QUERY_FUNC_STD_READ_REQ 0x01
-#define QUERY_FUNC_STD_WRITE_REQ 0x81
-
-typedef enum {
- UtpQueryFuncOpcodeNop = 0x00,
- UtpQueryFuncOpcodeRdDesc = 0x01,
- UtpQueryFuncOpcodeWrDesc = 0x02,
- UtpQueryFuncOpcodeRdAttr = 0x03,
- UtpQueryFuncOpcodeWrAttr = 0x04,
- UtpQueryFuncOpcodeRdFlag = 0x05,
- UtpQueryFuncOpcodeSetFlag = 0x06,
- UtpQueryFuncOpcodeClrFlag = 0x07,
- UtpQueryFuncOpcodeTogFlag = 0x08
-} UTP_QUERY_FUNC_OPCODE;
-
-//
-// UFS 2.0 Spec Section 10.5.11 - UTP Query Response UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x36*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2;
- UINT8 QueryFunc; /* Query Function */
- UINT8 QueryResp; /* Query Response */
- UINT8 Rsvd3;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian */
-
- //
- // DW3 - 6
- //
- UTP_UPIU_TSF Tsf; /* Transaction Specific Fields */
-
- //
- // DW7
- //
- UINT8 Rsvd4[4];
-
- //
- // Data Segment - Data to be transferred
- //
- // UINT8 Data[]; /* Data to be transferred, maximum is 65535 bytes */
-} UTP_QUERY_RESP_UPIU;
-
-typedef enum {
- UfsUtpQueryResponseSuccess = 0x00,
- UfsUtpQueryResponseParamNotReadable = 0xF6,
- UfsUtpQueryResponseParamNotWriteable = 0xF7,
- UfsUtpQueryResponseParamAlreadyWritten = 0xF8,
- UfsUtpQueryResponseInvalidLen = 0xF9,
- UfsUtpQueryResponseInvalidVal = 0xFA,
- UfsUtpQueryResponseInvalidSelector = 0xFB,
- UfsUtpQueryResponseInvalidIndex = 0xFC,
- UfsUtpQueryResponseInvalidIdn = 0xFD,
- UfsUtpQueryResponseInvalidOpc = 0xFE,
- UfsUtpQueryResponseGeneralFailure = 0xFF
-} UTP_QUERY_RESP_CODE;
-
-//
-// UFS 2.0 Spec Section 10.5.12 - UTP Reject UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x3F*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Lun;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd1[2];
- UINT8 Response; /* Response - 0x01 */
- UINT8 Rsvd2;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information - 0x00 */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3
- //
- UINT8 HdrSts; /* Basic Header Status */
- UINT8 Rsvd3;
- UINT8 E2ESts; /* End-to-End Status */
- UINT8 Rsvd4;
-
- //
- // DW4 - DW7
- //
- UINT8 Rsvd5[16];
-} UTP_REJ_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.13 - UTP NOP OUT UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x00*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2[4];
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 Rsvd3;
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3 - DW7
- //
- UINT8 Rsvd4[20];
-} UTP_NOP_OUT_UPIU;
-
-//
-// UFS 2.0 Spec Section 10.5.14 - UTP NOP IN UPIU
-//
-typedef struct {
- //
- // DW0
- //
- UINT8 TransCode : 6; /* Transaction Type - 0x20*/
- UINT8 Dd : 1;
- UINT8 Hd : 1;
- UINT8 Flags;
- UINT8 Rsvd1;
- UINT8 TaskTag; /* Task Tag */
-
- //
- // DW1
- //
- UINT8 Rsvd2[2];
- UINT8 Resp; /* Response - 0x00 */
- UINT8 Rsvd3;
-
- //
- // DW2
- //
- UINT8 EhsLen; /* Total EHS Length - 0x00 */
- UINT8 DevInfo; /* Device Information - 0x00 */
- UINT16 DataSegLen; /* Data Segment Length - Big Endian - 0x0000 */
-
- //
- // DW3 - DW7
- //
- UINT8 Rsvd4[20];
-} UTP_NOP_IN_UPIU;
-
-//
-// UFS Descriptors
-//
-typedef enum {
- UfsDeviceDesc = 0x00,
- UfsConfigDesc = 0x01,
- UfsUnitDesc = 0x02,
- UfsInterConnDesc = 0x04,
- UfsStringDesc = 0x05,
- UfsGeometryDesc = 0x07,
- UfsPowerDesc = 0x08
-} UFS_DESC_IDN;
-
-//
-// UFS 2.0 Spec Section 14.1.6.2 - Device Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 Device;
- UINT8 DevClass;
- UINT8 DevSubClass;
- UINT8 Protocol;
- UINT8 NumLun;
- UINT8 NumWLun;
- UINT8 BootEn;
- UINT8 DescAccessEn;
- UINT8 InitPowerMode;
- UINT8 HighPriorityLun;
- UINT8 SecureRemovalType;
- UINT8 SecurityLun;
- UINT8 BgOpsTermLat;
- UINT8 InitActiveIccLevel;
- UINT16 SpecVersion;
- UINT16 ManufactureDate;
- UINT8 ManufacturerName;
- UINT8 ProductName;
- UINT8 SerialName;
- UINT8 OemId;
- UINT16 ManufacturerId;
- UINT8 Ud0BaseOffset;
- UINT8 Ud0ConfParamLen;
- UINT8 DevRttCap;
- UINT16 PeriodicRtcUpdate;
- UINT8 Rsvd1[17];
- UINT8 Rsvd2[16];
-} UFS_DEV_DESC;
-
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 Rsvd1;
- UINT8 BootEn;
- UINT8 DescAccessEn;
- UINT8 InitPowerMode;
- UINT8 HighPriorityLun;
- UINT8 SecureRemovalType;
- UINT8 InitActiveIccLevel;
- UINT16 PeriodicRtcUpdate;
- UINT8 Rsvd2[5];
-} UFS_CONFIG_DESC_GEN_HEADER;
-
-typedef struct {
- UINT8 LunEn;
- UINT8 BootLunId;
- UINT8 LunWriteProt;
- UINT8 MemType;
- UINT32 NumAllocUnits;
- UINT8 DataReliability;
- UINT8 LogicBlkSize;
- UINT8 ProvisionType;
- UINT16 CtxCap;
- UINT8 Rsvd1[3];
-} UFS_UNIT_DESC_CONFIG_PARAMS;
-
-//
-// UFS 2.0 Spec Section 14.1.6.3 - Configuration Descriptor
-//
-typedef struct {
- UFS_CONFIG_DESC_GEN_HEADER Header;
- UFS_UNIT_DESC_CONFIG_PARAMS UnitDescConfParams[8];
-} UFS_CONFIG_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.4 - Geometry Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 MediaTech;
- UINT8 Rsvd1;
- UINT64 TotalRawDevCapacity;
- UINT8 Rsvd2;
- UINT32 SegSize;
- UINT8 AllocUnitSize;
- UINT8 MinAddrBlkSize;
- UINT8 OptReadBlkSize;
- UINT8 OptWriteBlkSize;
- UINT8 MaxInBufSize;
- UINT8 MaxOutBufSize;
- UINT8 RpmbRwSize;
- UINT8 Rsvd3;
- UINT8 DataOrder;
- UINT8 MaxCtxIdNum;
- UINT8 SysDataTagUnitSize;
- UINT8 SysDataResUnitSize;
- UINT8 SupSecRemovalTypes;
- UINT16 SupMemTypes;
- UINT32 SysCodeMaxNumAllocUnits;
- UINT16 SupCodeCapAdjFac;
- UINT32 NonPersMaxNumAllocUnits;
- UINT16 NonPersCapAdjFac;
- UINT32 Enhance1MaxNumAllocUnits;
- UINT16 Enhance1CapAdjFac;
- UINT32 Enhance2MaxNumAllocUnits;
- UINT16 Enhance2CapAdjFac;
- UINT32 Enhance3MaxNumAllocUnits;
- UINT16 Enhance3CapAdjFac;
- UINT32 Enhance4MaxNumAllocUnits;
- UINT16 Enhance4CapAdjFac;
-} UFS_GEOMETRY_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.5 - Unit Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 UnitIdx;
- UINT8 LunEn;
- UINT8 BootLunId;
- UINT8 LunWriteProt;
- UINT8 LunQueueDep;
- UINT8 Rsvd1;
- UINT8 MemType;
- UINT8 DataReliability;
- UINT8 LogicBlkSize;
- UINT64 LogicBlkCount;
- UINT32 EraseBlkSize;
- UINT8 ProvisionType;
- UINT64 PhyMemResCount;
- UINT16 CtxCap;
- UINT8 LargeUnitGranularity;
-} UFS_UNIT_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.6 - RPMB Unit Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT8 UnitIdx;
- UINT8 LunEn;
- UINT8 BootLunId;
- UINT8 LunWriteProt;
- UINT8 LunQueueDep;
- UINT8 Rsvd1;
- UINT8 MemType;
- UINT8 Rsvd2;
- UINT8 LogicBlkSize;
- UINT64 LogicBlkCount;
- UINT32 EraseBlkSize;
- UINT8 ProvisionType;
- UINT64 PhyMemResCount;
- UINT8 Rsvd3[3];
-} UFS_RPMB_UNIT_DESC;
-
-typedef struct {
- UINT16 Value : 10;
- UINT16 Rsvd1 : 4;
- UINT16 Unit : 2;
-} UFS_POWER_PARAM_ELEMENT;
-
-//
-// UFS 2.0 Spec Section 14.1.6.7 - Power Parameter Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UFS_POWER_PARAM_ELEMENT ActiveIccLevelVcc[16];
- UFS_POWER_PARAM_ELEMENT ActiveIccLevelVccQ[16];
- UFS_POWER_PARAM_ELEMENT ActiveIccLevelVccQ2[16];
-} UFS_POWER_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.8 - InterConnect Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- UINT16 UniProVer;
- UINT16 MphyVer;
-} UFS_INTER_CONNECT_DESC;
-
-//
-// UFS 2.0 Spec Section 14.1.6.9 - 14.1.6.12 - String Descriptor
-//
-typedef struct {
- UINT8 Length;
- UINT8 DescType;
- CHAR16 Unicode[126];
-} UFS_STRING_DESC;
-
-//
-// UFS 2.0 Spec Section 14.2 - Flags
-//
-typedef enum {
- UfsFlagDevInit = 0x01,
- UfsFlagPermWpEn = 0x02,
- UfsFlagPowerOnWpEn = 0x03,
- UfsFlagBgOpsEn = 0x04,
- UfsFlagPurgeEn = 0x06,
- UfsFlagPhyResRemoval = 0x08,
- UfsFlagBusyRtc = 0x09,
- UfsFlagPermDisFwUpdate = 0x0B
-} UFS_FLAGS_IDN;
-
-//
-// UFS 2.0 Spec Section 14.2 - Attributes
-//
-typedef enum {
- UfsAttrBootLunEn = 0x00,
- UfsAttrCurPowerMode = 0x02,
- UfsAttrActiveIccLevel = 0x03,
- UfsAttrOutOfOrderDataEn = 0x04,
- UfsAttrBgOpStatus = 0x05,
- UfsAttrPurgeStatus = 0x06,
- UfsAttrMaxDataInSize = 0x07,
- UfsAttrMaxDataOutSize = 0x08,
- UfsAttrDynCapNeeded = 0x09,
- UfsAttrRefClkFreq = 0x0a,
- UfsAttrConfigDescLock = 0x0b,
- UfsAttrMaxNumOfRtt = 0x0c,
- UfsAttrExceptionEvtCtrl = 0x0d,
- UfsAttrExceptionEvtSts = 0x0e,
- UfsAttrSecondsPassed = 0x0f,
- UfsAttrContextConf = 0x10,
- UfsAttrCorrPrgBlkNum = 0x11
-} UFS_ATTR_IDN;
-
-typedef enum {
- UfsNoData = 0,
- UfsDataOut = 1,
- UfsDataIn = 2,
- UfsDdReserved
-} UFS_DATA_DIRECTION;
-
-#pragma pack()
-
-#endif
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
index 2826ac1..3f24371 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.c
@@ -948,7 +948,6 @@ UsbBusBuildProtocol (
USB_DEVICE *RootHub;
USB_INTERFACE *RootIf;
EFI_STATUS Status;
- EFI_STATUS Status2;
UsbBus = AllocateZeroPool (sizeof (USB_BUS));
@@ -993,17 +992,8 @@ UsbBusBuildProtocol (
EFI_OPEN_PROTOCOL_BY_DRIVER
);
- Status2 = gBS->OpenProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- (VOID **)&(UsbBus->UsbHc),
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
-
- if (EFI_ERROR (Status) && EFI_ERROR (Status2)) {
- DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to open USB_HC/USB2_HC - %r\n", Status));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "UsbBusStart: Failed to open USB2_HC - %r\n", Status));
Status = EFI_DEVICE_ERROR;
goto CLOSE_HC;
@@ -1110,15 +1100,6 @@ CLOSE_HC:
);
}
- if (UsbBus->UsbHc != NULL) {
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
-
gBS->CloseProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
@@ -1180,7 +1161,6 @@ UsbBusControllerDriverSupported (
EFI_DEV_PATH_PTR DevicePathNode;
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
EFI_USB2_HC_PROTOCOL *Usb2Hc;
- EFI_USB_HC_PROTOCOL *UsbHc;
EFI_STATUS Status;
//
@@ -1225,47 +1205,20 @@ UsbBusControllerDriverSupported (
}
if (EFI_ERROR (Status)) {
- //
- // If failed to open USB_HC2, fall back to USB_HC
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- (VOID **)&UsbHc,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (Status == EFI_ALREADY_STARTED) {
- return EFI_SUCCESS;
- }
-
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Close the USB_HC used to perform the supported test
- //
- gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- } else {
- //
- // Close the USB_HC2 used to perform the supported test
- //
- gBS->CloseProtocol (
- Controller,
- &gEfiUsb2HcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
+ return Status;
}
//
+ // Close the USB_HC2 used to perform the supported test
+ //
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiUsb2HcProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ //
// Open the EFI Device Path protocol needed to perform the supported test
//
Status = gBS->OpenProtocol (
@@ -1546,15 +1499,6 @@ UsbBusControllerDriverStop (
);
}
- if (Bus->UsbHc != NULL) {
- Status = gBS->CloseProtocol (
- Controller,
- &gEfiUsbHcProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- }
-
if (!EFI_ERROR (Status)) {
gBS->CloseProtocol (
Controller,
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
index 21a2421..f9b32ff 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBus.h
@@ -13,7 +13,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Uefi.h>
#include <Protocol/Usb2HostController.h>
-#include <Protocol/UsbHostController.h>
#include <Protocol/UsbIo.h>
#include <Protocol/DevicePath.h>
@@ -243,7 +242,6 @@ struct _USB_BUS {
EFI_HANDLE HostHandle;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_USB2_HC_PROTOCOL *Usb2Hc;
- EFI_USB_HC_PROTOCOL *UsbHc;
//
// Recorded the max supported usb devices.
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
index dd85894..1dd0adf 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
@@ -62,7 +62,6 @@
## BY_START
gEfiDevicePathProtocolGuid
gEfiUsb2HcProtocolGuid ## TO_START
- gEfiUsbHcProtocolGuid ## TO_START
# [Event]
#
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
index b3a4063..713415d 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbEnumer.c
@@ -900,12 +900,17 @@ UsbEnumeratePort (
Child = NULL;
HubApi = HubIf->HubApi;
+ // Zero out PortState in case GetPortStatus does not set
+ // it and we continue on the EFI_DEVICE_ERROR path
+ PortState.PortStatus = 0;
+ PortState.PortChangeStatus = 0;
+
//
// Host learns of the new device by polling the hub for port changes.
//
Status = HubApi->GetPortStatus (HubIf, Port, &PortState);
- if (EFI_ERROR (Status)) {
+ if (EFI_ERROR (Status) && (Status != EFI_DEVICE_ERROR)) {
DEBUG ((DEBUG_ERROR, "UsbEnumeratePort: failed to get state of port %d\n", Port));
return Status;
}
@@ -987,7 +992,9 @@ UsbEnumeratePort (
// Now, new device connected, enumerate and configure the device
//
DEBUG ((DEBUG_INFO, "UsbEnumeratePort: new device connected at port %d\n", Port));
- if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET)) {
+ if (USB_BIT_IS_SET (PortState.PortChangeStatus, USB_PORT_STAT_C_RESET) &&
+ (Status != EFI_DEVICE_ERROR))
+ {
Status = UsbEnumerateNewDev (HubIf, Port, FALSE);
} else {
Status = UsbEnumerateNewDev (HubIf, Port, TRUE);
diff --git a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
index 740e7ba..eaffb8f 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusDxe/UsbUtility.c
@@ -63,19 +63,12 @@ UsbHcGetCapability (
{
EFI_STATUS Status;
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->GetCapability (
- UsbBus->Usb2Hc,
- MaxSpeed,
- NumOfPort,
- Is64BitCapable
- );
- } else {
- Status = UsbBus->UsbHc->GetRootHubPortNumber (UsbBus->UsbHc, NumOfPort);
-
- *MaxSpeed = EFI_USB_SPEED_FULL;
- *Is64BitCapable = (UINT8)FALSE;
- }
+ Status = UsbBus->Usb2Hc->GetCapability (
+ UsbBus->Usb2Hc,
+ MaxSpeed,
+ NumOfPort,
+ Is64BitCapable
+ );
return Status;
}
@@ -100,11 +93,7 @@ UsbHcGetRootHubPortStatus (
{
EFI_STATUS Status;
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->GetRootHubPortStatus (UsbBus->Usb2Hc, PortIndex, PortStatus);
- } else {
- Status = UsbBus->UsbHc->GetRootHubPortStatus (UsbBus->UsbHc, PortIndex, PortStatus);
- }
+ Status = UsbBus->Usb2Hc->GetRootHubPortStatus (UsbBus->Usb2Hc, PortIndex, PortStatus);
return Status;
}
@@ -129,11 +118,7 @@ UsbHcSetRootHubPortFeature (
{
EFI_STATUS Status;
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->SetRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature);
- } else {
- Status = UsbBus->UsbHc->SetRootHubPortFeature (UsbBus->UsbHc, PortIndex, Feature);
- }
+ Status = UsbBus->Usb2Hc->SetRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature);
return Status;
}
@@ -158,11 +143,7 @@ UsbHcClearRootHubPortFeature (
{
EFI_STATUS Status;
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->ClearRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature);
- } else {
- Status = UsbBus->UsbHc->ClearRootHubPortFeature (UsbBus->UsbHc, PortIndex, Feature);
- }
+ Status = UsbBus->Usb2Hc->ClearRootHubPortFeature (UsbBus->Usb2Hc, PortIndex, Feature);
return Status;
}
@@ -202,37 +183,20 @@ UsbHcControlTransfer (
)
{
EFI_STATUS Status;
- BOOLEAN IsSlowDevice;
-
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->ControlTransfer (
- UsbBus->Usb2Hc,
- DevAddr,
- DevSpeed,
- MaxPacket,
- Request,
- Direction,
- Data,
- DataLength,
- TimeOut,
- Translator,
- UsbResult
- );
- } else {
- IsSlowDevice = (BOOLEAN)(EFI_USB_SPEED_LOW == DevSpeed);
- Status = UsbBus->UsbHc->ControlTransfer (
- UsbBus->UsbHc,
- DevAddr,
- IsSlowDevice,
- (UINT8)MaxPacket,
- Request,
- Direction,
- Data,
- DataLength,
- TimeOut,
- UsbResult
- );
- }
+
+ Status = UsbBus->Usb2Hc->ControlTransfer (
+ UsbBus->Usb2Hc,
+ DevAddr,
+ DevSpeed,
+ MaxPacket,
+ Request,
+ Direction,
+ Data,
+ DataLength,
+ TimeOut,
+ Translator,
+ UsbResult
+ );
return Status;
}
@@ -277,34 +241,20 @@ UsbHcBulkTransfer (
{
EFI_STATUS Status;
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->BulkTransfer (
- UsbBus->Usb2Hc,
- DevAddr,
- EpAddr,
- DevSpeed,
- MaxPacket,
- BufferNum,
- Data,
- DataLength,
- DataToggle,
- TimeOut,
- Translator,
- UsbResult
- );
- } else {
- Status = UsbBus->UsbHc->BulkTransfer (
- UsbBus->UsbHc,
- DevAddr,
- EpAddr,
- (UINT8)MaxPacket,
- *Data,
- DataLength,
- DataToggle,
- TimeOut,
- UsbResult
- );
- }
+ Status = UsbBus->Usb2Hc->BulkTransfer (
+ UsbBus->Usb2Hc,
+ DevAddr,
+ EpAddr,
+ DevSpeed,
+ MaxPacket,
+ BufferNum,
+ Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ Translator,
+ UsbResult
+ );
return Status;
}
@@ -348,40 +298,21 @@ UsbHcAsyncInterruptTransfer (
)
{
EFI_STATUS Status;
- BOOLEAN IsSlowDevice;
-
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->AsyncInterruptTransfer (
- UsbBus->Usb2Hc,
- DevAddr,
- EpAddr,
- DevSpeed,
- MaxPacket,
- IsNewTransfer,
- DataToggle,
- PollingInterval,
- DataLength,
- Translator,
- Callback,
- Context
- );
- } else {
- IsSlowDevice = (BOOLEAN)(EFI_USB_SPEED_LOW == DevSpeed);
-
- Status = UsbBus->UsbHc->AsyncInterruptTransfer (
- UsbBus->UsbHc,
- DevAddr,
- EpAddr,
- IsSlowDevice,
- (UINT8)MaxPacket,
- IsNewTransfer,
- DataToggle,
- PollingInterval,
- DataLength,
- Callback,
- Context
- );
- }
+
+ Status = UsbBus->Usb2Hc->AsyncInterruptTransfer (
+ UsbBus->Usb2Hc,
+ DevAddr,
+ EpAddr,
+ DevSpeed,
+ MaxPacket,
+ IsNewTransfer,
+ DataToggle,
+ PollingInterval,
+ DataLength,
+ Translator,
+ Callback,
+ Context
+ );
return Status;
}
@@ -423,37 +354,20 @@ UsbHcSyncInterruptTransfer (
)
{
EFI_STATUS Status;
- BOOLEAN IsSlowDevice;
-
- if (UsbBus->Usb2Hc != NULL) {
- Status = UsbBus->Usb2Hc->SyncInterruptTransfer (
- UsbBus->Usb2Hc,
- DevAddr,
- EpAddr,
- DevSpeed,
- MaxPacket,
- Data,
- DataLength,
- DataToggle,
- TimeOut,
- Translator,
- UsbResult
- );
- } else {
- IsSlowDevice = (BOOLEAN)((EFI_USB_SPEED_LOW == DevSpeed) ? TRUE : FALSE);
- Status = UsbBus->UsbHc->SyncInterruptTransfer (
- UsbBus->UsbHc,
- DevAddr,
- EpAddr,
- IsSlowDevice,
- (UINT8)MaxPacket,
- Data,
- DataLength,
- DataToggle,
- TimeOut,
- UsbResult
- );
- }
+
+ Status = UsbBus->Usb2Hc->SyncInterruptTransfer (
+ UsbBus->Usb2Hc,
+ DevAddr,
+ EpAddr,
+ DevSpeed,
+ MaxPacket,
+ Data,
+ DataLength,
+ DataToggle,
+ TimeOut,
+ Translator,
+ UsbResult
+ );
return Status;
}
@@ -473,29 +387,17 @@ UsbOpenHostProtoByChild (
IN EFI_HANDLE Child
)
{
- EFI_USB_HC_PROTOCOL *UsbHc;
EFI_USB2_HC_PROTOCOL *Usb2Hc;
EFI_STATUS Status;
- if (Bus->Usb2Hc != NULL) {
- Status = gBS->OpenProtocol (
- Bus->HostHandle,
- &gEfiUsb2HcProtocolGuid,
- (VOID **)&Usb2Hc,
- mUsbBusDriverBinding.DriverBindingHandle,
- Child,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- } else {
- Status = gBS->OpenProtocol (
- Bus->HostHandle,
- &gEfiUsbHcProtocolGuid,
- (VOID **)&UsbHc,
- mUsbBusDriverBinding.DriverBindingHandle,
- Child,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- }
+ Status = gBS->OpenProtocol (
+ Bus->HostHandle,
+ &gEfiUsb2HcProtocolGuid,
+ (VOID **)&Usb2Hc,
+ mUsbBusDriverBinding.DriverBindingHandle,
+ Child,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
return Status;
}
@@ -513,21 +415,12 @@ UsbCloseHostProtoByChild (
IN EFI_HANDLE Child
)
{
- if (Bus->Usb2Hc != NULL) {
- gBS->CloseProtocol (
- Bus->HostHandle,
- &gEfiUsb2HcProtocolGuid,
- mUsbBusDriverBinding.DriverBindingHandle,
- Child
- );
- } else {
- gBS->CloseProtocol (
- Bus->HostHandle,
- &gEfiUsbHcProtocolGuid,
- mUsbBusDriverBinding.DriverBindingHandle,
- Child
- );
- }
+ gBS->CloseProtocol (
+ Bus->HostHandle,
+ &gEfiUsb2HcProtocolGuid,
+ mUsbBusDriverBinding.DriverBindingHandle,
+ Child
+ );
}
/**
diff --git a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
index 6ea4495..159cd19 100644
--- a/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
+++ b/MdeModulePkg/Bus/Usb/UsbBusPei/UsbPeim.c
@@ -1,6 +1,7 @@
/** @file
The module to produce Usb Bus PPI.
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -428,6 +429,7 @@ PeiUsbEnumeration (
UINT8 CurrentAddress;
UINTN InterfaceIndex;
UINTN EndpointIndex;
+ UINT8 UsbEnumLoop;
CurrentAddress = 0;
if (Usb2HcPpi != NULL) {
@@ -449,179 +451,149 @@ PeiUsbEnumeration (
DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: NumOfRootPort: %x\n", NumOfRootPort));
- for (Index = 0; Index < NumOfRootPort; Index++) {
- //
- // First get root port status to detect changes happen
- //
- if (Usb2HcPpi != NULL) {
- Usb2HcPpi->GetRootHubPortStatus (
- PeiServices,
- Usb2HcPpi,
- (UINT8)Index,
- &PortStatus
- );
- } else {
- UsbHcPpi->GetRootHubPortStatus (
- PeiServices,
- UsbHcPpi,
- (UINT8)Index,
- &PortStatus
- );
- }
-
- DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
- //
- // Only handle connection/enable/overcurrent/reset change.
- //
- if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
- continue;
- } else {
- if (IsPortConnect (PortStatus.PortStatus)) {
- MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- MemPages,
- &AllocateAddress
+ //
+ // USB3.x devices initially appear in USB2.0 ports. When the USB2.0 port is reset, the USB3.x device disappears
+ // from the USB2.0 port and appears on the USB3.0 port. The USB3.x device won't be enumerated if the USB2.0 port
+ // number is greater than the USB3.0 port number. Re-enumerate USB to make sure USB3.x devices in this case.
+ //
+ for (UsbEnumLoop = 0; UsbEnumLoop < 2; UsbEnumLoop++) {
+ for (Index = 0; Index < NumOfRootPort; Index++) {
+ //
+ // First get root port status to detect changes happen
+ //
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->GetRootHubPortStatus (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8)Index,
+ &PortStatus
);
- if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
- }
+ } else {
+ UsbHcPpi->GetRootHubPortStatus (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8)Index,
+ &PortStatus
+ );
+ }
- PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
- ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
+ DEBUG ((DEBUG_INFO, "USB Status --- Port: %x ConnectChange[%04x] Status[%04x]\n", Index, PortStatus.PortChangeStatus, PortStatus.PortStatus));
+ //
+ // Only handle connection/enable/overcurrent/reset change.
+ //
+ if ((PortStatus.PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
+ continue;
+ } else {
+ if (IsPortConnect (PortStatus.PortStatus)) {
+ MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ MemPages,
+ &AllocateAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
- PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
- PeiUsbDevice->DeviceAddress = 0;
- PeiUsbDevice->MaxPacketSize0 = 8;
- PeiUsbDevice->DataToggle = 0;
- CopyMem (
- &(PeiUsbDevice->UsbIoPpi),
- &mUsbIoPpi,
- sizeof (PEI_USB_IO_PPI)
- );
- CopyMem (
- &(PeiUsbDevice->UsbIoPpiList),
- &mUsbIoPpiList,
- sizeof (EFI_PEI_PPI_DESCRIPTOR)
- );
- PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
- PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
- PeiUsbDevice->UsbHcPpi = UsbHcPpi;
- PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
- PeiUsbDevice->IsHub = 0x0;
- PeiUsbDevice->DownStreamPortNo = 0x0;
+ PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
+ ZeroMem (PeiUsbDevice, sizeof (PEI_USB_DEVICE));
- if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
- ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))
- {
- //
- // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
- //
- ResetRootPort (
- PeiServices,
- PeiUsbDevice->UsbHcPpi,
- PeiUsbDevice->Usb2HcPpi,
- Index,
- 0
+ PeiUsbDevice->Signature = PEI_USB_DEVICE_SIGNATURE;
+ PeiUsbDevice->DeviceAddress = 0;
+ PeiUsbDevice->MaxPacketSize0 = 8;
+ PeiUsbDevice->DataToggle = 0;
+ CopyMem (
+ &(PeiUsbDevice->UsbIoPpi),
+ &mUsbIoPpi,
+ sizeof (PEI_USB_IO_PPI)
);
-
- if (Usb2HcPpi != NULL) {
- Usb2HcPpi->GetRootHubPortStatus (
- PeiServices,
- Usb2HcPpi,
- (UINT8)Index,
- &PortStatus
- );
- } else {
- UsbHcPpi->GetRootHubPortStatus (
- PeiServices,
- UsbHcPpi,
- (UINT8)Index,
- &PortStatus
- );
- }
- } else {
- if (Usb2HcPpi != NULL) {
- Usb2HcPpi->ClearRootHubPortFeature (
- PeiServices,
- Usb2HcPpi,
- (UINT8)Index,
- EfiUsbPortResetChange
- );
+ CopyMem (
+ &(PeiUsbDevice->UsbIoPpiList),
+ &mUsbIoPpiList,
+ sizeof (EFI_PEI_PPI_DESCRIPTOR)
+ );
+ PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+ PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
+ PeiUsbDevice->UsbHcPpi = UsbHcPpi;
+ PeiUsbDevice->Usb2HcPpi = Usb2HcPpi;
+ PeiUsbDevice->IsHub = 0x0;
+ PeiUsbDevice->DownStreamPortNo = 0x0;
+
+ if (((PortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0) ||
+ ((PortStatus.PortStatus & (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE)) == 0))
+ {
+ //
+ // If the port already has reset change flag and is connected and enabled, skip the port reset logic.
+ //
+ ResetRootPort (
+ PeiServices,
+ PeiUsbDevice->UsbHcPpi,
+ PeiUsbDevice->Usb2HcPpi,
+ Index,
+ 0
+ );
+
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->GetRootHubPortStatus (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8)Index,
+ &PortStatus
+ );
+ } else {
+ UsbHcPpi->GetRootHubPortStatus (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8)Index,
+ &PortStatus
+ );
+ }
} else {
- UsbHcPpi->ClearRootHubPortFeature (
- PeiServices,
- UsbHcPpi,
- (UINT8)Index,
- EfiUsbPortResetChange
- );
+ if (Usb2HcPpi != NULL) {
+ Usb2HcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ Usb2HcPpi,
+ (UINT8)Index,
+ EfiUsbPortResetChange
+ );
+ } else {
+ UsbHcPpi->ClearRootHubPortFeature (
+ PeiServices,
+ UsbHcPpi,
+ (UINT8)Index,
+ EfiUsbPortResetChange
+ );
+ }
}
- }
- PeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
- DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
+ PeiUsbDevice->DeviceSpeed = (UINT8)PeiUsbGetDeviceSpeed (PortStatus.PortStatus);
+ DEBUG ((DEBUG_INFO, "Device Speed =%d\n", PeiUsbDevice->DeviceSpeed));
- if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {
- PeiUsbDevice->MaxPacketSize0 = 512;
- } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
- PeiUsbDevice->MaxPacketSize0 = 64;
- } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
- PeiUsbDevice->MaxPacketSize0 = 8;
- } else {
- PeiUsbDevice->MaxPacketSize0 = 8;
- }
-
- //
- // Configure that Usb Device
- //
- Status = PeiConfigureUsbDevice (
- PeiServices,
- PeiUsbDevice,
- Index,
- &CurrentAddress
- );
-
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
-
- Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
-
- if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
- PeiUsbDevice->IsHub = 0x1;
-
- Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
- if (EFI_ERROR (Status)) {
- return Status;
+ if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_SUPER_SPEED)) {
+ PeiUsbDevice->MaxPacketSize0 = 512;
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_HIGH_SPEED)) {
+ PeiUsbDevice->MaxPacketSize0 = 64;
+ } else if (USB_BIT_IS_SET (PortStatus.PortStatus, USB_PORT_STAT_LOW_SPEED)) {
+ PeiUsbDevice->MaxPacketSize0 = 8;
+ } else {
+ PeiUsbDevice->MaxPacketSize0 = 8;
}
- PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
- }
-
- for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
//
- // Begin to deal with the new device
+ // Configure that Usb Device
//
- MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
- Status = PeiServicesAllocatePages (
- EfiBootServicesCode,
- MemPages,
- &AllocateAddress
- );
+ Status = PeiConfigureUsbDevice (
+ PeiServices,
+ PeiUsbDevice,
+ Index,
+ &CurrentAddress
+ );
+
if (EFI_ERROR (Status)) {
- return EFI_OUT_OF_RESOURCES;
+ continue;
}
- CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
- PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
- PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
- PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
- PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
- for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
- PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
- }
+ DEBUG ((DEBUG_INFO, "PeiUsbEnumeration: PeiConfigureUsbDevice Success\n"));
Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
@@ -635,11 +607,48 @@ PeiUsbEnumeration (
PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
}
+
+ for (InterfaceIndex = 1; InterfaceIndex < PeiUsbDevice->ConfigDesc->NumInterfaces; InterfaceIndex++) {
+ //
+ // Begin to deal with the new device
+ //
+ MemPages = sizeof (PEI_USB_DEVICE) / EFI_PAGE_SIZE + 1;
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ MemPages,
+ &AllocateAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem ((VOID *)(UINTN)AllocateAddress, PeiUsbDevice, sizeof (PEI_USB_DEVICE));
+ PeiUsbDevice = (PEI_USB_DEVICE *)((UINTN)AllocateAddress);
+ PeiUsbDevice->AllocateAddress = (UINTN)AllocateAddress;
+ PeiUsbDevice->UsbIoPpiList.Ppi = &PeiUsbDevice->UsbIoPpi;
+ PeiUsbDevice->InterfaceDesc = PeiUsbDevice->InterfaceDescList[InterfaceIndex];
+ for (EndpointIndex = 0; EndpointIndex < PeiUsbDevice->InterfaceDesc->NumEndpoints; EndpointIndex++) {
+ PeiUsbDevice->EndpointDesc[EndpointIndex] = PeiUsbDevice->EndpointDescList[InterfaceIndex][EndpointIndex];
+ }
+
+ Status = PeiServicesInstallPpi (&PeiUsbDevice->UsbIoPpiList);
+
+ if (PeiUsbDevice->InterfaceDesc->InterfaceClass == 0x09) {
+ PeiUsbDevice->IsHub = 0x1;
+
+ Status = PeiDoHubConfig (PeiServices, PeiUsbDevice);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PeiHubEnumeration (PeiServices, PeiUsbDevice, &CurrentAddress);
+ }
+ }
+ } else {
+ //
+ // Disconnect change happen, currently we don't support
+ //
}
- } else {
- //
- // Disconnect change happen, currently we don't support
- //
}
}
}
diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
index f648187..8c09831 100644
--- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
+++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBoot.c
@@ -210,7 +210,7 @@ UsbBootExecCmd (
//
// If command execution failed, then retrieve error info via sense request.
//
- DEBUG ((DEBUG_ERROR, "UsbBootExecCmd: %r to Exec 0x%x Cmd (Result = %x)\n", Status, *(UINT8 *)Cmd, CmdResult));
+ DEBUG ((DEBUG_INFO, "UsbBootExecCmd: %r to Exec 0x%x Cmd (Result = %x)\n", Status, *(UINT8 *)Cmd, CmdResult));
return UsbBootRequestSense (UsbMass);
}
diff --git a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c
index 55c239d..c4efa6b 100644
--- a/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c
+++ b/MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassBot.c
@@ -449,8 +449,7 @@ UsbBotExecCommand (
@param Context The context of the BOT protocol, that is,
USB_BOT_PROTOCOL.
- @param ExtendedVerification If FALSE, just issue Bulk-Only Mass Storage Reset request.
- If TRUE, additionally reset parent hub port.
+ @param ExtendedVerification ExtendedVerification is ignored in this implementation.
@retval EFI_SUCCESS The device is reset.
@retval Others Failed to reset the device..
@@ -470,16 +469,6 @@ UsbBotResetDevice (
UsbBot = (USB_BOT_PROTOCOL *)Context;
- if (ExtendedVerification) {
- //
- // If we need to do strictly reset, reset its parent hub port
- //
- Status = UsbBot->UsbIo->UsbPortReset (UsbBot->UsbIo);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- }
-
//
// Issue a class specific Bulk-Only Mass Storage Reset request,
// according to section 3.1 of USB Mass Storage Class Bulk-Only Transport Spec, v1.0.
diff --git a/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c b/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c
index ad5f066..5706ccd 100644
--- a/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c
+++ b/MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolutePointer.c
@@ -847,7 +847,7 @@ OnMouseInterruptComplete (
UsbMouseAbsolutePointerDevice->State.CurrentZ =
MIN (
MAX (
- (INT64)UsbMouseAbsolutePointerDevice->State.CurrentZ + *((INT8 *)Data + 1),
+ (INT64)UsbMouseAbsolutePointerDevice->State.CurrentZ + *((INT8 *)Data + 3),
(INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMinZ
),
(INT64)UsbMouseAbsolutePointerDevice->Mode.AbsoluteMaxZ
diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcEcm/UsbEcmFunction.c b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcEcm/UsbEcmFunction.c
index 0c1f252..dc78466 100644
--- a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcEcm/UsbEcmFunction.c
+++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcEcm/UsbEcmFunction.c
@@ -111,7 +111,7 @@ GetFunctionalDescriptor (
for (Offset = 0; NextDescriptor (Config, &Offset);) {
Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + Offset);
- if (Interface->DescriptorType == CS_INTERFACE) {
+ if (Interface->DescriptorType == USB_DESC_TYPE_CS_INTERFACE) {
if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype == FunDescriptorType) {
switch (FunDescriptorType) {
case HEADER_FUN_DESCRIPTOR:
diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c
index ef01a6f..4b6e0d2 100644
--- a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c
+++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbNcmFunction.c
@@ -111,7 +111,7 @@ GetFunctionalDescriptor (
for (Offset = 0; NextDescriptor (Config, &Offset);) {
Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + Offset);
- if (Interface->DescriptorType == CS_INTERFACE) {
+ if (Interface->DescriptorType == USB_DESC_TYPE_CS_INTERFACE) {
if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype == FunDescriptorType) {
switch (FunDescriptorType) {
case HEADER_FUN_DESCRIPTOR:
diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c
index 6d45a1b..8723a82 100644
--- a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c
+++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c
@@ -123,7 +123,7 @@ GetFunctionalDescriptor (
for (Offset = 0; NextDescriptor (Config, &Offset);) {
Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + Offset);
- if (Interface->DescriptorType == CS_INTERFACE) {
+ if (Interface->DescriptorType == USB_DESC_TYPE_CS_INTERFACE) {
if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype == FunDescriptorType) {
switch (FunDescriptorType) {
case HEADER_FUN_DESCRIPTOR:
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h
index 53e2670..6f08554 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.h
+++ b/MdeModulePkg/Core/Dxe/DxeMain.h
@@ -45,6 +45,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/HiiPackageList.h>
#include <Protocol/SmmBase2.h>
#include <Protocol/PeCoffImageEmulator.h>
+#include <Protocol/MemoryAttribute.h>
#include <Guid/MemoryTypeInformation.h>
#include <Guid/FirmwareFileSystem2.h>
#include <Guid/FirmwareFileSystem3.h>
@@ -84,6 +85,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DxeServicesLib.h>
#include <Library/DebugAgentLib.h>
#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/OrderedCollectionLib.h>
//
// attributes for reserved memory before it is promoted to system memory
@@ -249,6 +251,7 @@ extern EFI_SECURITY_ARCH_PROTOCOL *gSecurity;
extern EFI_SECURITY2_ARCH_PROTOCOL *gSecurity2;
extern EFI_BDS_ARCH_PROTOCOL *gBds;
extern EFI_SMM_BASE2_PROTOCOL *gSmmBase2;
+extern EFI_MEMORY_ATTRIBUTE_PROTOCOL *gMemoryAttributeProtocol;
extern EFI_TPL gEfiCurrentTpl;
@@ -2790,4 +2793,15 @@ MergeMemoryMap (
IN UINTN DescriptorSize
);
+/**
+ Initializes "handle" support.
+
+ @return Status code.
+
++**/
+EFI_STATUS
+CoreInitializeHandleServices (
+ VOID
+ );
+
#endif
diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf
index 090970a..40e7dc8 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -95,6 +95,7 @@
CpuExceptionHandlerLib
PcdLib
ImagePropertiesRecordLib
+ OrderedCollectionLib
[Guids]
gEfiEventMemoryMapChangeGuid ## PRODUCES ## Event
@@ -155,6 +156,7 @@
gEfiHiiPackageListProtocolGuid ## SOMETIMES_PRODUCES
gEfiSmmBase2ProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiPeCoffImageEmulatorProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiMemoryAttributeProtocolGuid ## CONSUMES
# Arch Protocols
gEfiBdsArchProtocolGuid ## CONSUMES
diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
index 17d510a..50ab5fb 100644
--- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
+++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
@@ -203,6 +203,8 @@ EFI_HANDLE gDxeCoreImageHandle = NULL;
BOOLEAN gMemoryMapTerminated = FALSE;
+static BOOLEAN mExitBootServicesCalled = FALSE;
+
//
// EFI Decompress Protocol
//
@@ -277,6 +279,12 @@ DxeMain (
MemoryProfileInit (HobStart);
//
+ // Start the Handle Services.
+ //
+ Status = CoreInitializeHandleServices ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
// Start the Image Services.
//
Status = CoreInitializeImageServices (HobStart);
@@ -455,6 +463,11 @@ DxeMain (
Status = CoreInitializeEventServices ();
ASSERT_EFI_ERROR (Status);
+ //
+ // Give the debug agent a chance to initialize with events.
+ //
+ InitializeDebugAgent (DEBUG_AGENT_INIT_DXE_CORE_LATE, HobStart, NULL);
+
MemoryProfileInstallProtocol ();
CoreInitializeMemoryAttributesTable ();
@@ -772,7 +785,10 @@ CoreExitBootServices (
// Notify other drivers of their last chance to use boot services
// before the memory map is terminated.
//
- CoreNotifySignalList (&gEfiEventBeforeExitBootServicesGuid);
+ if (!mExitBootServicesCalled) {
+ CoreNotifySignalList (&gEfiEventBeforeExitBootServicesGuid);
+ mExitBootServicesCalled = TRUE;
+ }
//
// Disable Timer
diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
index 9936450..f5cac18 100644
--- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
+++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
@@ -26,7 +26,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
EFI_RESOURCE_ATTRIBUTE_64_BIT_IO | \
- EFI_RESOURCE_ATTRIBUTE_PERSISTENT )
+ EFI_RESOURCE_ATTRIBUTE_PERSISTENT | \
+ EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE )
#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
@@ -93,6 +94,7 @@ GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {
{ 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 },
+ { EFI_RESOURCE_ATTRIBUTE_HOT_PLUGGABLE, EFI_MEMORY_HOT_PLUGGABLE, TRUE },
{ 0, 0, FALSE }
};
@@ -151,6 +153,13 @@ CoreDumpGcdMemorySpaceMap (
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
UINTN Index;
+ // The compiler is not smart enough to compile out the whole function if DEBUG_GCD is not enabled, so we end up
+ // looping through the GCD every time it gets updated, which wastes a lot of needless cycles if we aren't going to
+ // print it. So shortcircuit and jump out if we don't need to print it.
+ if (!DebugPrintLevelEnabled (DEBUG_GCD)) {
+ return;
+ }
+
Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
ASSERT (Status == EFI_SUCCESS && MemorySpaceMap != NULL);
@@ -197,6 +206,13 @@ CoreDumpGcdIoSpaceMap (
EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;
UINTN Index;
+ // The compiler is not smart enough to compile out the whole function if DEBUG_GCD is not enabled, so we end up
+ // looping through the GCD every time it gets updated, which wastes a lot of needless cycles if we aren't going to
+ // print it. So shortcircuit and jump out if we don't need to print it.
+ if (!DebugPrintLevelEnabled (DEBUG_GCD)) {
+ return;
+ }
+
Status = CoreGetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);
ASSERT (Status == EFI_SUCCESS && IoSpaceMap != NULL);
@@ -974,7 +990,7 @@ CoreConvertSpace (
// Set attributes operation
//
case GCD_SET_ATTRIBUTES_MEMORY_OPERATION:
- if (CpuArchAttributes == 0) {
+ if ((CpuArchAttributes == 0) && (Attributes != 0)) {
//
// Keep original CPU arch attributes when caller just calls
// SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME).
@@ -989,6 +1005,20 @@ CoreConvertSpace (
//
case GCD_SET_CAPABILITIES_MEMORY_OPERATION:
Entry->Capabilities = Capabilities;
+
+ // Only SystemMemory and MoreReliable memory is in gMemoryMap
+ // so only attempt to update the attributes there if this is
+ // a relevant GCD type
+ if ((Entry->GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||
+ (Entry->GcdMemoryType == EfiGcdMemoryTypeMoreReliable))
+ {
+ CoreUpdateMemoryAttributes (
+ BaseAddress,
+ RShiftU64 (Length, EFI_PAGE_SHIFT),
+ Capabilities & (~EFI_MEMORY_RUNTIME)
+ );
+ }
+
break;
}
@@ -1700,17 +1730,10 @@ CoreSetMemorySpaceCapabilities (
IN UINT64 Capabilities
)
{
- EFI_STATUS Status;
-
DEBUG ((DEBUG_GCD, "GCD:CoreSetMemorySpaceCapabilities(Base=%016lx,Length=%016lx)\n", BaseAddress, Length));
DEBUG ((DEBUG_GCD, " Capabilities = %016lx\n", Capabilities));
- Status = CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE)0, (EFI_GCD_IO_TYPE)0, BaseAddress, Length, Capabilities, 0);
- if (!EFI_ERROR (Status)) {
- CoreUpdateMemoryAttributes (BaseAddress, RShiftU64 (Length, EFI_PAGE_SHIFT), Capabilities & (~EFI_MEMORY_RUNTIME));
- }
-
- return Status;
+ return CoreConvertSpace (GCD_SET_CAPABILITIES_MEMORY_OPERATION, (EFI_GCD_MEMORY_TYPE)0, (EFI_GCD_IO_TYPE)0, BaseAddress, Length, Capabilities, 0);
}
/**
@@ -2661,6 +2684,12 @@ CoreInitializeGcdServices (
GcdMemoryType = EfiGcdMemoryTypePersistent;
}
+ // Mark special purpose memory as system memory, if it was system memory in the HOB
+ // However, if this is also marked as persistent, let persistent take precedence
+ if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE) == EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE) {
+ GcdMemoryType = EfiGcdMemoryTypeSystemMemory;
+ }
+
break;
case EFI_RESOURCE_MEMORY_MAPPED_IO:
case EFI_RESOURCE_FIRMWARE_DEVICE:
diff --git a/MdeModulePkg/Core/Dxe/Hand/Handle.c b/MdeModulePkg/Core/Dxe/Hand/Handle.c
index 24e4fbf..93e69ee 100644
--- a/MdeModulePkg/Core/Dxe/Hand/Handle.c
+++ b/MdeModulePkg/Core/Dxe/Hand/Handle.c
@@ -15,10 +15,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase
// gHandleDatabaseKey - The Key to show that the handle has been created/modified
//
-LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
-LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
-EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
-UINT64 gHandleDatabaseKey = 0;
+LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
+LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
+EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
+UINT64 gHandleDatabaseKey = 0;
+ORDERED_COLLECTION *gOrderedHandleList = NULL;
/**
Acquire lock on gProtocolDatabaseLock.
@@ -45,6 +46,60 @@ CoreReleaseProtocolLock (
}
/**
+ Comparator function for two opaque pointers, ordering on (unsigned) pointer
+ value itself.
+ Can be used as both Key and UserStruct comparator.
+
+ @param[in] Pointer1 First pointer.
+
+ @param[in] Pointer2 Second pointer.
+
+ @retval <0 If Pointer1 compares less than Pointer2.
+
+ @retval 0 If Pointer1 compares equal to Pointer2.
+
+ @retval >0 If Pointer1 compares greater than Pointer2.
+**/
+STATIC
+INTN
+EFIAPI
+PointerCompare (
+ IN CONST VOID *Pointer1,
+ IN CONST VOID *Pointer2
+ )
+{
+ if (Pointer1 == Pointer2) {
+ return 0;
+ }
+
+ if ((UINTN)Pointer1 < (UINTN)Pointer2) {
+ return -1;
+ }
+
+ return 1;
+}
+
+/**
+ Initializes "handle" support.
+
+ @return Status code.
+
+**/
+EFI_STATUS
+CoreInitializeHandleServices (
+ VOID
+ )
+{
+ gOrderedHandleList = OrderedCollectionInit (PointerCompare, PointerCompare);
+
+ if (gOrderedHandleList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
Check whether a handle is a valid EFI_HANDLE
The gProtocolDatabaseLock must be owned
@@ -59,8 +114,7 @@ CoreValidateHandle (
IN EFI_HANDLE UserHandle
)
{
- IHANDLE *Handle;
- LIST_ENTRY *Link;
+ ORDERED_COLLECTION_ENTRY *Entry;
if (UserHandle == NULL) {
return EFI_INVALID_PARAMETER;
@@ -68,11 +122,9 @@ CoreValidateHandle (
ASSERT_LOCKED (&gProtocolDatabaseLock);
- for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {
- Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
- if (Handle == (IHANDLE *)UserHandle) {
- return EFI_SUCCESS;
- }
+ Entry = OrderedCollectionFind (gOrderedHandleList, UserHandle);
+ if (Entry != NULL) {
+ return EFI_SUCCESS;
}
return EFI_INVALID_PARAMETER;
@@ -453,6 +505,16 @@ CoreInstallProtocolInterfaceNotify (
}
//
+ // Add this handle to the ordered list of all handles
+ // in the system
+ //
+ Status = OrderedCollectionInsert (gOrderedHandleList, NULL, Handle);
+ if (EFI_ERROR (Status)) {
+ CoreFreePool (Handle);
+ goto Done;
+ }
+
+ //
// Initialize new handler structure
//
Handle->Signature = EFI_HANDLE_SIGNATURE;
@@ -825,6 +887,11 @@ CoreUninstallProtocolInterface (
//
if (IsListEmpty (&Handle->Protocols)) {
Handle->Signature = 0;
+ OrderedCollectionDelete (
+ gOrderedHandleList,
+ OrderedCollectionFind (gOrderedHandleList, Handle),
+ NULL
+ );
RemoveEntryList (&Handle->AllHandles);
CoreFreePool (Handle);
}
@@ -1040,6 +1107,8 @@ CoreOpenProtocol (
return EFI_INVALID_PARAMETER;
}
+ Prot = NULL;
+
//
// Lock the protocol database
//
diff --git a/MdeModulePkg/Core/Dxe/Image/Image.c b/MdeModulePkg/Core/Dxe/Image/Image.c
index 37fc74d..8d12f93 100644
--- a/MdeModulePkg/Core/Dxe/Image/Image.c
+++ b/MdeModulePkg/Core/Dxe/Image/Image.c
@@ -1725,7 +1725,9 @@ CoreStartImage (
// Image has completed. Verify the tpl is the same
//
ASSERT (Image->Tpl == gEfiCurrentTpl);
- CoreRestoreTpl (Image->Tpl);
+ if (Image->Tpl != gEfiCurrentTpl) {
+ CoreRestoreTpl (Image->Tpl);
+ }
CoreFreePool (Image->JumpBuffer);
diff --git a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
index 0c0ca61..4071053 100644
--- a/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
+++ b/MdeModulePkg/Core/Dxe/Mem/HeapGuard.c
@@ -1406,34 +1406,39 @@ GuardAllFreedPages (
TableEntry = ((UINT64 *)(UINTN)(Tables[Level]))[Indices[Level]];
Address = Addresses[Level];
- if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
- Level += 1;
- Tables[Level] = TableEntry;
- Addresses[Level] = Address;
- Indices[Level] = 0;
-
- continue;
+ if (TableEntry == 0) {
+ GuardPageNumber = 0;
+ GuardPage = (UINT64)-1;
} else {
- BitIndex = 1;
- while (BitIndex != 0) {
- if ((TableEntry & BitIndex) != 0) {
- if (GuardPage == (UINT64)-1) {
- GuardPage = Address;
+ if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
+ Level += 1;
+ Tables[Level] = TableEntry;
+ Addresses[Level] = Address;
+ Indices[Level] = 0;
+
+ continue;
+ } else {
+ BitIndex = 1;
+ while (BitIndex != 0) {
+ if ((TableEntry & BitIndex) != 0) {
+ if (GuardPage == (UINT64)-1) {
+ GuardPage = Address;
+ }
+
+ ++GuardPageNumber;
+ } else if (GuardPageNumber > 0) {
+ GuardFreedPages (GuardPage, GuardPageNumber);
+ GuardPageNumber = 0;
+ GuardPage = (UINT64)-1;
}
- ++GuardPageNumber;
- } else if (GuardPageNumber > 0) {
- GuardFreedPages (GuardPage, GuardPageNumber);
- GuardPageNumber = 0;
- GuardPage = (UINT64)-1;
- }
+ if (TableEntry == 0) {
+ break;
+ }
- if (TableEntry == 0) {
- break;
+ Address += EFI_PAGES_TO_SIZE (1);
+ BitIndex = LShiftU64 (BitIndex, 1);
}
-
- Address += EFI_PAGES_TO_SIZE (1);
- BitIndex = LShiftU64 (BitIndex, 1);
}
}
}
diff --git a/MdeModulePkg/Core/Dxe/Mem/Imem.h b/MdeModulePkg/Core/Dxe/Mem/Imem.h
index 2f0bf2b..84027d6 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Imem.h
+++ b/MdeModulePkg/Core/Dxe/Mem/Imem.h
@@ -10,22 +10,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define _IMEM_H_
//
-// +---------------------------------------------------+
-// | 0..(EfiMaxMemoryType - 1) - Normal memory type |
-// +---------------------------------------------------+
-// | EfiMaxMemoryType..0x6FFFFFFF - Invalid |
-// +---------------------------------------------------+
-// | 0x70000000..0x7FFFFFFF - OEM reserved |
-// +---------------------------------------------------+
-// | 0x80000000..0xFFFFFFFF - OS reserved |
-// +---------------------------------------------------+
-//
-#define MEMORY_TYPE_OS_RESERVED_MIN 0x80000000
-#define MEMORY_TYPE_OS_RESERVED_MAX 0xFFFFFFFF
-#define MEMORY_TYPE_OEM_RESERVED_MIN 0x70000000
-#define MEMORY_TYPE_OEM_RESERVED_MAX 0x7FFFFFFF
-
-//
// MEMORY_MAP_ENTRY
//
diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c
index e4daa74..27c2788 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -1459,6 +1459,11 @@ CoreInternalAllocatePages (
// return EFI_NOT_FOUND.
//
if (Type == AllocateAddress) {
+ // Page 0 is not allowed to be allocated as it is reserved for null pointer detection
+ if (Start == 0) {
+ return EFI_NOT_FOUND;
+ }
+
if ((NumberOfPages == 0) ||
(NumberOfPages > RShiftU64 (MaxAddress, EFI_PAGE_SHIFT)))
{
@@ -1741,6 +1746,38 @@ CoreFreePages (
{
EFI_STATUS Status;
EFI_MEMORY_TYPE MemoryType;
+ UINT64 Attributes;
+
+ // check if this memory is returned to the core as RW at a minimum. If the memory attribute protocol is not installed,
+ // then we assume that the memory is RW by default and continue to free it.
+ if (gMemoryAttributeProtocol != NULL) {
+ Status = gMemoryAttributeProtocol->GetMemoryAttributes (
+ gMemoryAttributeProtocol,
+ Memory,
+ EFI_PAGES_TO_SIZE (NumberOfPages),
+ &Attributes
+ );
+
+ // if we failed to get the attributes, or if the memory is read-only or read-protected,
+ // then we leak the memory and return success. This is done because the UEFI spec does not specify whether pages
+ // should be freed with any specific permission attributes. As such, there exist bootloaders in the wild that will
+ // free memory that is marked RO, which can crash the core if DebugClearMemory is enabled or can be passed out to a
+ // driver in the next AllocatePages() call, which can cause a crash later on. It is deemed lower risk to leak the
+ // memory than to attempt to fix up the attributes as that requires syncing the GCD and the page table.
+ if (EFI_ERROR (Status) || (Attributes & EFI_MEMORY_RO) || (Attributes & EFI_MEMORY_RP)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: Memory %llx for %llx Pages failed to get attributes with status %r or it is read-only or read-protected. "
+ "Attributes: %llx. Leaking memory!\n",
+ __func__,
+ Memory,
+ NumberOfPages,
+ Status,
+ Attributes
+ ));
+ return EFI_SUCCESS;
+ }
+ }
Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType);
if (!EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
index eeb18f6..54061bf 100644
--- a/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
+++ b/MdeModulePkg/Core/Dxe/Misc/DebugImageInfo.c
@@ -177,20 +177,7 @@ CoreNewDebugImageInfoEntry (
Table = mDebugInfoTableHeader.EfiDebugImageInfoTable;
- if (mDebugInfoTableHeader.TableSize < mMaxTableEntries) {
- //
- // We still have empty entires in the Table, find the first empty entry.
- //
- Index = 0;
- while (Table[Index].NormalImage != NULL) {
- Index++;
- }
-
- //
- // There must be an empty entry in the in the table.
- //
- ASSERT (Index < mMaxTableEntries);
- } else {
+ if (mDebugInfoTableHeader.TableSize >= mMaxTableEntries) {
//
// Table is full, so re-allocate another page for a larger table...
//
@@ -218,10 +205,12 @@ CoreNewDebugImageInfoEntry (
// Enlarge the max table entries and set the first empty entry index to
// be the original max table entries.
//
- Index = mMaxTableEntries;
mMaxTableEntries += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE;
}
+ // We always put the next entry at the end of the currently consumed table (i.e. first free entry)
+ Index = mDebugInfoTableHeader.TableSize;
+
//
// Allocate data for new entry
//
@@ -264,11 +253,13 @@ CoreRemoveDebugImageInfoEntry (
for (Index = 0; Index < mMaxTableEntries; Index++) {
if ((Table[Index].NormalImage != NULL) && (Table[Index].NormalImage->ImageHandle == ImageHandle)) {
//
- // Found a match. Free up the record, then NULL the pointer to indicate the slot
- // is free.
+ // Found a match. Free up the record, then move the final entry down to this slot; we don't care about the
+ // order of the array
//
CoreFreePool (Table[Index].NormalImage);
- Table[Index].NormalImage = NULL;
+ Table[Index].NormalImage = Table[mDebugInfoTableHeader.TableSize - 1].NormalImage;
+ Table[mDebugInfoTableHeader.TableSize - 1].NormalImage = NULL;
+
//
// Decrease the number of EFI_DEBUG_IMAGE_INFO elements and set the mDebugInfoTable in modified status.
//
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
index e9343a2..a11c455 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
@@ -395,11 +395,14 @@ MergeMemoryMap (
NewMemoryMapEntry = MemoryMap;
MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);
while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
- CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
+ CopyMem (NewMemoryMapEntry, MemoryMapEntry, DescriptorSize);
NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
do {
- MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);
+ if ((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) {
+ MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);
+ }
+
MemoryBlockLength = LShiftU64 (NewMemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT);
if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
(NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
@@ -426,7 +429,7 @@ MergeMemoryMap (
/**
Enforce memory map attributes.
- This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
+ This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
@param MemoryMap A pointer to the buffer in which firmware places
the current memory map.
@@ -447,18 +450,23 @@ EnforceMemoryMapAttribute (
MemoryMapEntry = MemoryMap;
MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
- switch (MemoryMapEntry->Type) {
- case EfiRuntimeServicesCode:
- // do nothing
- break;
- case EfiRuntimeServicesData:
- case EfiMemoryMappedIO:
- case EfiMemoryMappedIOPortSpace:
- MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
- break;
- case EfiReservedMemoryType:
- case EfiACPIMemoryNVS:
- break;
+ if ((MemoryMapEntry->Attribute & EFI_MEMORY_ACCESS_MASK) == 0) {
+ switch (MemoryMapEntry->Type) {
+ case EfiRuntimeServicesCode:
+ // If at this point the attributes have not been set on an EfiRuntimeServicesCode
+ // region, the memory range must not contain a loaded image. It's possible these
+ // non-image EfiRuntimeServicesCode regions are part of the unused memory bucket.
+ // It could also be that this region was explicitly allocated outside of the PE
+ // loader but the UEFI spec requires that all EfiRuntimeServicesCode regions contain
+ // EFI modules. In either case, set the attributes to RO and XP.
+ MemoryMapEntry->Attribute |= (EFI_MEMORY_RO | EFI_MEMORY_XP);
+ break;
+ case EfiRuntimeServicesData:
+ MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
+ break;
+ default:
+ break;
+ }
}
MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index 2c069cc..69d26cb 100644
--- a/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -38,6 +38,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Guid/MemoryAttributesTable.h>
#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/MemoryAttribute.h>
#include <Protocol/SimpleFileSystem.h>
#include "DxeMain.h"
@@ -67,6 +68,8 @@ extern LIST_ENTRY mGcdMemorySpaceMap;
STATIC LIST_ENTRY mProtectedImageRecordList;
+EFI_MEMORY_ATTRIBUTE_PROTOCOL *gMemoryAttributeProtocol;
+
/**
Get the image type.
@@ -194,16 +197,113 @@ SetUefiImageMemoryAttributes (
EFI_STATUS Status;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
UINT64 FinalAttributes;
+ UINT64 CurrentAddress;
+ UINT64 CurrentLength;
+ UINT64 ImageEnd;
+ UINT64 DescEnd;
+
+ CurrentAddress = BaseAddress;
+ ImageEnd = BaseAddress + Length;
+
+ // we loop here because we may have multiple memory space descriptors that overlap the requested range
+ // this will definitely be the case for unprotecting an image, because that calls this function for the entire image,
+ // which we split into different GCD descriptors when we protected it.
+ while (CurrentAddress < BaseAddress + Length) {
+ Status = CoreGetMemorySpaceDescriptor (CurrentAddress, &Descriptor);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a - Failed to get memory space descriptor for address %llx with status %r. Cannot protect image.\n",
+ __func__,
+ CurrentAddress,
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
- Status = CoreGetMemorySpaceDescriptor (BaseAddress, &Descriptor);
- ASSERT_EFI_ERROR (Status);
+ DescEnd = Descriptor.BaseAddress + Descriptor.Length;
- FinalAttributes = (Descriptor.Attributes & EFI_CACHE_ATTRIBUTE_MASK) | (Attributes & EFI_MEMORY_ATTRIBUTE_MASK);
+ // ensure that we only change the attributes for the range that we are interested in, not the entire descriptor, we
+ // may also be in the middle of a descriptor, so ensure our length is not larger than the descriptor length
+ if (ImageEnd > DescEnd) {
+ CurrentLength = DescEnd - CurrentAddress;
+ } else {
+ CurrentLength = ImageEnd - CurrentAddress;
+ }
+
+ // Preserve the existing caching and virtual attributes, but remove the hardware access bits
+ FinalAttributes = (Descriptor.Attributes & ~EFI_MEMORY_ACCESS_MASK) | (Attributes & EFI_MEMORY_ATTRIBUTE_MASK);
+
+ DEBUG ((DEBUG_VERBOSE, "SetUefiImageMemoryAttributes - 0x%016lx - 0x%016lx (0x%016lx)\n", CurrentAddress, CurrentLength, FinalAttributes));
- DEBUG ((DEBUG_INFO, "SetUefiImageMemoryAttributes - 0x%016lx - 0x%016lx (0x%016lx)\n", BaseAddress, Length, FinalAttributes));
+ // check to see if the capabilities support the attributes we want to set. If not, set the capabilities appropriately
+ if ((Descriptor.Capabilities & FinalAttributes) != FinalAttributes) {
+ Status = CoreSetMemorySpaceCapabilities (
+ CurrentAddress,
+ CurrentLength,
+ Descriptor.Capabilities | FinalAttributes
+ );
+
+ // if we failed to set the capabilities, we should try to continue, it is possible we could succeed
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a failed setting capabilities on %llx of length %llx with capabilities %llx - %r\n",
+ __func__,
+ CurrentAddress,
+ CurrentLength,
+ Descriptor.Capabilities | FinalAttributes,
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ // Call into the GCD to update the attributes there. It will call into the CPU Arch protocol to update the
+ // page table attributes
+ Status = CoreSetMemorySpaceAttributes (
+ CurrentAddress,
+ CurrentLength,
+ FinalAttributes
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a failed on %llx of length %llx with attributes %llx - %r\n",
+ __func__,
+ CurrentAddress,
+ CurrentLength,
+ FinalAttributes,
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ }
- ASSERT (gCpu != NULL);
- gCpu->SetMemoryAttributes (gCpu, BaseAddress, Length, FinalAttributes);
+ if (((FinalAttributes & (EFI_MEMORY_ATTRIBUTE_MASK | EFI_CACHE_ATTRIBUTE_MASK)) == 0) && (gCpu != NULL)) {
+ // if the passed hardware attributes are 0, CoreSetMemorySpaceAttributes() will not call into the CPU Arch protocol
+ // to set the attributes, so we need to do it manually here. This can be the case when we are unprotecting an
+ // image if no caching attributes are set. If gCpu has not been populated yet, we'll still have updated the GCD
+ // descriptor and we should sync the attributes with the CPU Arch protocol when it is available.
+ Status = gCpu->SetMemoryAttributes (gCpu, CurrentAddress, CurrentLength, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a failed to update page table for %llx of length %llx with attributes 0 - %r\n",
+ __func__,
+ CurrentAddress,
+ CurrentLength,
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ // we may have started in the middle of a descriptor, so we need to move to the beginning of the next descriptor,
+ // or the end of the image, whichever is smaller
+ CurrentAddress += CurrentLength;
+ }
}
/**
@@ -371,6 +471,19 @@ ProtectUefiImage (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a failed to create image properties record\n", __func__));
+
+ // if we failed to create the image properties record, this may mean that the image is not aligned properly
+ // the GCD will believe that this memory is non-executable, because the NX initialization routine doesn't know what
+ // memory is image memory or not, even though the page table has the correct attributes, so we need to set the
+ // attributes here to RWX so that future updates to the GCD do not apply the NX attributes to this memory in the
+ // page table (as can happen when applying virtual attributes). This may have the side effect of marking other
+ // memory as RWX, since this image may not be page aligned, but that is safe to do, it may just remove some
+ // page protections, but it already has to to execute this image.
+ SetUefiImageMemoryAttributes (
+ (UINT64)(UINTN)LoadedImage->ImageBase & ~EFI_PAGE_MASK,
+ (LoadedImage->ImageSize + EFI_PAGE_MASK) & ~EFI_PAGE_MASK,
+ 0
+ );
FreePool (ImageRecord);
goto Finish;
}
@@ -924,6 +1037,37 @@ DisableNullDetectionAtTheEndOfDxe (
}
/**
+ A notification for the Memory Attribute Protocol Installation.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the notification function's context,
+ which is implementation-dependent.
+
+**/
+VOID
+EFIAPI
+MemoryAttributeProtocolNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiMemoryAttributeProtocolGuid, NULL, (VOID **)&gMemoryAttributeProtocol);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_INFO,
+ "%a - Unable to locate the memory attribute protocol! Status = %r\n",
+ __func__,
+ Status
+ ));
+ }
+
+ CoreCloseEvent (Event);
+}
+
+/**
Initialize Memory Protection support.
**/
VOID
@@ -974,6 +1118,35 @@ CoreInitializeMemoryProtection (
);
ASSERT_EFI_ERROR (Status);
+ // Register an event to populate the memory attribute protocol
+ Status = CoreCreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ MemoryAttributeProtocolNotify,
+ NULL,
+ &Event
+ );
+
+ // if we fail to create the event or the protocol notify, we should still continue, we won't be able to query the
+ // memory attributes on FreePages(), so we may encounter a driver or bootloader that has not set attributes back to
+ // RW, but this matches the state of the world before this protocol was introduced, so it is not a regression.
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a - Failed to create event for the Memory Attribute Protocol notification: %r\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ // Register for protocol notification
+ Status = CoreRegisterProtocolNotify (
+ &gEfiMemoryAttributeProtocolGuid,
+ Event,
+ &Registration
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a - Failed to register for the Memory Attribute Protocol notification: %r\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+
//
// Register a callback to disable NULL pointer detection at EndOfDxe
//
diff --git a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
index 2c19f1a..0b3a71f 100644
--- a/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
+++ b/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c
@@ -3,7 +3,7 @@
Responsibility of this module is to load the DXE Core from a Firmware Volume.
Copyright (c) 2016 HP Development Company, L.P.
-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
**/
@@ -59,7 +59,7 @@ CONST EFI_PEI_NOTIFY_DESCRIPTOR mMemoryDiscoveredNotifyList = {
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
- @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
+ @retval EFI_SUCCESS The entry point of DXE IPL PEIM executes successfully.
@retval Others Some error occurs during the execution of this function.
**/
@@ -80,7 +80,7 @@ PeimInitializeDxeIpl (
Status = PeiServicesRegisterForShadow (FileHandle);
if (Status == EFI_SUCCESS) {
//
- // EFI_SUCESS means it is the first time to call register for shadow.
+ // EFI_SUCCESS means it is the first time to call register for shadow.
//
return Status;
}
@@ -487,10 +487,10 @@ DxeIplFindDxeCore (
//
if (EFI_ERROR (Status)) {
REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_EC_DXE_CORRUPT));
+ ASSERT_EFI_ERROR (Status);
+ break;
}
- ASSERT_EFI_ERROR (Status);
-
//
// Find the DxeCore file type from the beginning in this firmware volume.
//
@@ -509,6 +509,13 @@ DxeIplFindDxeCore (
//
Instance++;
}
+
+ //
+ // DxeCore cannot find in any firmware volume.
+ //
+ CpuDeadLoop ();
+
+ return NULL;
}
/**
@@ -629,6 +636,11 @@ CustomGuidedSectionExtract (
ScratchBuffer,
AuthenticationStatus
);
+
+ if (ScratchBuffer != NULL) {
+ FreePages (ScratchBuffer, EFI_SIZE_TO_PAGES (ScratchBufferSize));
+ }
+
if (EFI_ERROR (Status)) {
//
// Decode failed
diff --git a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index 65e9bdc..98aae5a 100644
--- a/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -166,7 +166,7 @@ Create4GPageTablesIa32Pae (
// Protect the page table by marking the memory used for page table to be
// read-only.
//
- EnablePageTableProtection ((UINTN)PageMap, FALSE);
+ EnablePageTableProtection ((UINTN)PageMap, 3);
return (UINTN)PageMap;
}
@@ -265,14 +265,6 @@ HandOffToDxeCore (
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
BOOLEAN BuildPageTablesIa32Pae;
- //
- // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
- //
- if (IsNullDetectionEnabled ()) {
- ClearFirst4KPage (HobList.Raw);
- BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);
- }
-
Status = PeiServicesAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack);
ASSERT_EFI_ERROR (Status);
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
index fa2050c..034254b 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
@@ -37,14 +37,6 @@ HandOffToDxeCore (
UINTN GhcbSize;
//
- // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
- //
- if (IsNullDetectionEnabled ()) {
- ClearFirst4KPage (HobList.Raw);
- BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);
- }
-
- //
// Get Vector Hand-off Info PPI and build Guided HOB
//
Status = PeiServicesLocatePpi (
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
index df6196a..ee85b31 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
@@ -32,72 +32,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
PAGE_TABLE_POOL *mPageTablePool = NULL;
/**
- Clear legacy memory located at the first 4K-page, if available.
-
- This function traverses the whole HOB list to check if memory from 0 to 4095
- exists and has not been allocated, and then clear it if so.
-
- @param HobStart The start of HobList passed to DxeCore.
-
-**/
-VOID
-ClearFirst4KPage (
- IN VOID *HobStart
- )
-{
- EFI_PEI_HOB_POINTERS RscHob;
- EFI_PEI_HOB_POINTERS MemHob;
- BOOLEAN DoClear;
-
- RscHob.Raw = HobStart;
- MemHob.Raw = HobStart;
- DoClear = FALSE;
-
- //
- // Check if page 0 exists and free
- //
- while ((RscHob.Raw = GetNextHob (
- EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
- RscHob.Raw
- )) != NULL)
- {
- if ((RscHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
- (RscHob.ResourceDescriptor->PhysicalStart == 0))
- {
- DoClear = TRUE;
- //
- // Make sure memory at 0-4095 has not been allocated.
- //
- while ((MemHob.Raw = GetNextHob (
- EFI_HOB_TYPE_MEMORY_ALLOCATION,
- MemHob.Raw
- )) != NULL)
- {
- if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
- < EFI_PAGE_SIZE)
- {
- DoClear = FALSE;
- break;
- }
-
- MemHob.Raw = GET_NEXT_HOB (MemHob);
- }
-
- break;
- }
-
- RscHob.Raw = GET_NEXT_HOB (RscHob);
- }
-
- if (DoClear) {
- DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
- SetMem (NULL, EFI_PAGE_SIZE, 0);
- }
-
- return;
-}
-
-/**
Return configure status of NULL pointer detection feature.
@return TRUE NULL pointer detection feature is enabled
@@ -485,14 +419,14 @@ Split1GPageTo2M (
@param[in] PageTableBase Base address of page table (CR3).
@param[in] Address Start address of a page to be set as read-only.
- @param[in] Level4Paging Level 4 paging flag.
+ @param[in] LevelOfPaging Level of paging.
**/
VOID
SetPageTablePoolReadOnly (
IN UINTN PageTableBase,
IN EFI_PHYSICAL_ADDRESS Address,
- IN BOOLEAN Level4Paging
+ IN UINT8 LevelOfPaging
)
{
UINTN Index;
@@ -502,9 +436,9 @@ SetPageTablePoolReadOnly (
UINT64 *PageTable;
UINT64 *NewPageTable;
UINT64 PageAttr;
- UINT64 LevelSize[5];
- UINT64 LevelMask[5];
- UINTN LevelShift[5];
+ UINT64 LevelSize[6];
+ UINT64 LevelMask[6];
+ UINTN LevelShift[6];
UINTN Level;
UINT64 PoolUnitSize;
@@ -521,23 +455,26 @@ SetPageTablePoolReadOnly (
LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;
LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;
LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;
+ LevelShift[5] = PAGING_L5_ADDRESS_SHIFT;
LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;
LevelMask[2] = PAGING_2M_ADDRESS_MASK_64;
LevelMask[3] = PAGING_1G_ADDRESS_MASK_64;
- LevelMask[4] = PAGING_1G_ADDRESS_MASK_64;
+ LevelMask[4] = PAGING_512G_ADDRESS_MASK_64;
+ LevelMask[5] = PAGING_256T_ADDRESS_MASK_64;
LevelSize[1] = SIZE_4KB;
LevelSize[2] = SIZE_2MB;
LevelSize[3] = SIZE_1GB;
LevelSize[4] = SIZE_512GB;
+ LevelSize[5] = SIZE_256TB;
AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) &
PAGING_1G_ADDRESS_MASK_64;
PageTable = (UINT64 *)(UINTN)PageTableBase;
PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;
- for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) {
+ for (Level = LevelOfPaging; Level > 0; --Level) {
Index = ((UINTN)RShiftU64 (Address, LevelShift[Level]));
Index &= PAGING_PAE_INDEX_MASK;
@@ -607,13 +544,13 @@ SetPageTablePoolReadOnly (
Prevent the memory pages used for page table from been overwritten.
@param[in] PageTableBase Base address of page table (CR3).
- @param[in] Level4Paging Level 4 paging flag.
+ @param[in] LevelOfPaging Level of paging.
**/
VOID
EnablePageTableProtection (
- IN UINTN PageTableBase,
- IN BOOLEAN Level4Paging
+ IN UINTN PageTableBase,
+ IN UINT8 LevelOfPaging
)
{
PAGE_TABLE_POOL *HeadPool;
@@ -642,7 +579,7 @@ EnablePageTableProtection (
// protection to them one by one.
//
while (PoolSize > 0) {
- SetPageTablePoolReadOnly (PageTableBase, Address, Level4Paging);
+ SetPageTablePoolReadOnly (PageTableBase, Address, LevelOfPaging);
Address += PAGE_TABLE_POOL_UNIT_SIZE;
PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;
}
@@ -696,7 +633,7 @@ CreateIdentityMappingPageTables (
UINTN TotalPagesNum;
UINTN BigPageAddress;
VOID *Hob;
- BOOLEAN Page5LevelEnabled;
+ UINT8 LevelOfPaging;
BOOLEAN Page1GSupport;
PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
UINT64 AddressEncMask;
@@ -743,16 +680,16 @@ CreateIdentityMappingPageTables (
//
// If cpu has already run in 64bit long mode PEI, Page table Level in DXE must align with previous level.
//
- Cr4.UintN = AsmReadCr4 ();
- Page5LevelEnabled = (Cr4.Bits.LA57 != 0);
- if (Page5LevelEnabled) {
+ Cr4.UintN = AsmReadCr4 ();
+ LevelOfPaging = (Cr4.Bits.LA57 == 1) ? 5 : 4;
+ if (LevelOfPaging == 5) {
ASSERT (PcdGetBool (PcdUse5LevelPageTable));
}
} else {
//
// If cpu runs in 32bit protected mode PEI, Page table Level in DXE is decided by PCD and feature capability.
//
- Page5LevelEnabled = FALSE;
+ LevelOfPaging = 4;
if (PcdGetBool (PcdUse5LevelPageTable)) {
AsmCpuidEx (
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
@@ -763,12 +700,12 @@ CreateIdentityMappingPageTables (
NULL
);
if (EcxFlags.Bits.FiveLevelPage != 0) {
- Page5LevelEnabled = TRUE;
+ LevelOfPaging = 5;
}
}
}
- DEBUG ((DEBUG_INFO, "AddressBits=%u 5LevelPaging=%u 1GPage=%u\n", PhysicalAddressBits, Page5LevelEnabled, Page1GSupport));
+ DEBUG ((DEBUG_INFO, "AddressBits=%u LevelOfPaging=%u 1GPage=%u\n", PhysicalAddressBits, LevelOfPaging, Page1GSupport));
//
// IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses
@@ -776,7 +713,7 @@ CreateIdentityMappingPageTables (
// due to either unsupported by HW, or disabled by PCD.
//
ASSERT (PhysicalAddressBits <= 52);
- if (!Page5LevelEnabled && (PhysicalAddressBits > 48)) {
+ if ((LevelOfPaging != 5) && (PhysicalAddressBits > 48)) {
PhysicalAddressBits = 48;
}
@@ -811,7 +748,7 @@ CreateIdentityMappingPageTables (
//
// Substract the one page occupied by PML5 entries if 5-Level Paging is disabled.
//
- if (!Page5LevelEnabled) {
+ if (LevelOfPaging != 5) {
TotalPagesNum--;
}
@@ -831,7 +768,7 @@ CreateIdentityMappingPageTables (
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
//
PageMap = (VOID *)BigPageAddress;
- if (Page5LevelEnabled) {
+ if (LevelOfPaging == 5) {
//
// By architecture only one PageMapLevel5 exists - so lets allocate storage for it.
//
@@ -853,7 +790,7 @@ CreateIdentityMappingPageTables (
PageMapLevel4Entry = (VOID *)BigPageAddress;
BigPageAddress += SIZE_4KB;
- if (Page5LevelEnabled) {
+ if (LevelOfPaging == 5) {
//
// Make a PML5 Entry
//
@@ -947,7 +884,7 @@ CreateIdentityMappingPageTables (
ZeroMem (PageMapLevel4Entry, (512 - IndexOfPml4Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER));
}
- if (Page5LevelEnabled) {
+ if (LevelOfPaging == 5) {
Cr4.UintN = AsmReadCr4 ();
Cr4.Bits.LA57 = 1;
AsmWriteCr4 (Cr4.UintN);
@@ -961,7 +898,7 @@ CreateIdentityMappingPageTables (
// Protect the page table by marking the memory used for page table to be
// read-only.
//
- EnablePageTableProtection ((UINTN)PageMap, TRUE);
+ EnablePageTableProtection ((UINTN)PageMap, LevelOfPaging);
//
// Set IA32_EFER.NXE if necessary.
diff --git a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
index 616ebe4..95e88a9 100644
--- a/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
+++ b/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
@@ -149,14 +149,17 @@ typedef union {
#define PAGING_PAE_INDEX_MASK 0x1FF
-#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
-#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
-#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+#define PAGING_512G_ADDRESS_MASK_64 0x000FF80000000000ull
+#define PAGING_256T_ADDRESS_MASK_64 0x000F800000000000ull
#define PAGING_L1_ADDRESS_SHIFT 12
#define PAGING_L2_ADDRESS_SHIFT 21
#define PAGING_L3_ADDRESS_SHIFT 30
#define PAGING_L4_ADDRESS_SHIFT 39
+#define PAGING_L5_ADDRESS_SHIFT 48
#define PAGING_PML4E_NUMBER 4
@@ -265,20 +268,6 @@ AsmGetVectorTemplatInfo (
);
/**
- Clear legacy memory located at the first 4K-page.
-
- This function traverses the whole HOB list to check if memory from 0 to 4095
- exists and has not been allocated, and then clear it if so.
-
- @param HobStart The start of HobList passed to DxeCore.
-
-**/
-VOID
-ClearFirst4KPage (
- IN VOID *HobStart
- );
-
-/**
Return configure status of NULL pointer detection feature.
@return TRUE NULL pointer detection feature is enabled
@@ -293,13 +282,13 @@ IsNullDetectionEnabled (
Prevent the memory pages used for page table from been overwritten.
@param[in] PageTableBase Base address of page table (CR3).
- @param[in] Level4Paging Level 4 paging flag.
+ @param[in] LevelOfPaging Level of paging.
**/
VOID
EnablePageTableProtection (
- IN UINTN PageTableBase,
- IN BOOLEAN Level4Paging
+ IN UINTN PageTableBase,
+ IN UINT8 LevelOfPaging
);
/**
diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index ca37bde..4073bad 100644
--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -3,14 +3,382 @@
Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PeiMain.h"
+//
+// Utility global variables
+//
+
+/**
+ DelayedDispatchDispatcher
+
+ Delayed Dispach cycle (ie one pass) through each entry, calling functions when their
+ time has expired. When DelayedGroupId is specified, if there are any of the specified entries
+ in the dispatch queue during dispatch, repeat the DelayedDispatch cycle.
+
+ @param DelayedDispatchTable Pointer to dispatch table
+ @param OPTIONAL DelayedGroupId used to insure particular time is met.
+
+ @return BOOLEAN
+**/
+BOOLEAN
+DelayedDispatchDispatcher (
+ IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable,
+ IN EFI_GUID *DelayedGroupId OPTIONAL
+ );
+
+/**
+ DelayedDispatch End of PEI callback function. Insure that all of the delayed dispatch
+ entries are complete before exiting PEI.
+
+ @param[in] PeiServices - Pointer to PEI Services Table.
+ @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi - Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS - Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PeiDelayedDispatchOnEndOfPei (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ );
+
+EFI_DELAYED_DISPATCH_PPI mDelayedDispatchPpi = { PeiDelayedDispatchRegister, PeiDelayedDispatchWaitOnEvent };
+EFI_PEI_PPI_DESCRIPTOR mDelayedDispatchDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiDelayedDispatchPpiGuid,
+ &mDelayedDispatchPpi
+};
+
+EFI_PEI_NOTIFY_DESCRIPTOR mDelayedDispatchNotifyDesc = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiEndOfPeiSignalPpiGuid,
+ PeiDelayedDispatchOnEndOfPei
+};
+
+/**
+ Helper function to look up DELAYED_DISPATCH_TABLE published in HOB.
+
+ @return Pointer to DELAYED_DISPATCH_TABLE from HOB
+**/
+DELAYED_DISPATCH_TABLE *
+GetDelayedDispatchTable (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid);
+ if (GuidHob == NULL) {
+ // There is something off about the build if this happens. We do want to
+ // assert here to catch it during development.
+ DEBUG ((DEBUG_ERROR, "%a - Delayed Dispatch Hob not available.\n", __func__));
+ ASSERT (FALSE);
+ return NULL;
+ }
+
+ return (DELAYED_DISPATCH_TABLE *)GET_GUID_HOB_DATA (GuidHob);
+}
+
+/**
+ Register a callback to be called after a minimum delay has occurred.
+
+ This service is the single member function of the EFI_DELAYED_DISPATCH_PPI
+
+ @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI instance
+ @param[in] Function Function to call back
+ @param[in] Context Context data
+ @param[in] DelayedGroupId GUID for this Delayed Dispatch request.
+ @param[in] Delay Delay interval
+
+ @retval EFI_SUCCESS Function successfully loaded
+ @retval EFI_INVALID_PARAMETER One of the Arguments is not supported
+ @retval EFI_OUT_OF_RESOURCES No more entries
+
+**/
+EFI_STATUS
+EFIAPI
+PeiDelayedDispatchRegister (
+ IN EFI_DELAYED_DISPATCH_PPI *This,
+ IN EFI_DELAYED_DISPATCH_FUNCTION Function,
+ IN UINT64 Context,
+ IN EFI_GUID *DelayedGroupId OPTIONAL,
+ IN UINT32 Delay
+ )
+{
+ DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
+ DELAYED_DISPATCH_ENTRY *Entry;
+ EFI_STATUS Status;
+
+ // Check input parameters
+ if ((Function == NULL) || (Delay > FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs)) || (This == NULL)) {
+ DEBUG ((DEBUG_ERROR, "%a Invalid parameter. Function: %Lx, Delay: %u, This: %p\n", __func__, (UINT64)(UINTN)Function, Delay, This));
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ // Get delayed dispatch table
+ DelayedDispatchTable = GetDelayedDispatchTable ();
+ if (DelayedDispatchTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", __func__));
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ // Check for available entry slots
+ ASSERT (DelayedDispatchTable->Count <= DELAYED_DISPATCH_MAX_ENTRIES);
+ if (DelayedDispatchTable->Count == DELAYED_DISPATCH_MAX_ENTRIES) {
+ DEBUG ((DEBUG_ERROR, "%a Too many entries requested\n", __func__));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ Entry = &DelayedDispatchTable->Entry[DelayedDispatchTable->Count];
+ Entry->Function = Function;
+ Entry->Context = Context;
+ Status = SafeUint64Add (GET_TIME_IN_US (), Delay, &Entry->DispatchTime);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a Delay overflow\n", __func__));
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ if (DelayedGroupId == NULL) {
+ ZeroMem (&Entry->DelayedGroupId, sizeof (EFI_GUID));
+ } else {
+ CopyGuid (&Entry->DelayedGroupId, DelayedGroupId);
+ }
+
+ Entry->MicrosecondDelay = Delay;
+ DelayedDispatchTable->Count++;
+
+ DEBUG ((DEBUG_INFO, "%a Adding dispatch Entry\n", __func__));
+ DEBUG ((DEBUG_INFO, " Requested Delay = %d\n", Delay));
+ DEBUG ((DEBUG_INFO, " Trigger Time = %d\n", Entry->DispatchTime));
+ DEBUG ((DEBUG_INFO, " Context = 0x%016lx\n", Entry->Context));
+ DEBUG ((DEBUG_INFO, " Function = %Lx\n", (UINT64)(UINTN)Entry->Function));
+ DEBUG ((DEBUG_INFO, " DelayedGroupId = %g\n", &Entry->DelayedGroupId));
+
+ if (Delay == 0) {
+ // Force early dispatch point
+ DelayedDispatchDispatcher (DelayedDispatchTable, NULL);
+ }
+
+ Status = EFI_SUCCESS;
+
+Exit:
+ return Status;
+}
+
+/**
+ DelayedDispatchDispatcher
+
+ Delayed Dispach cycle (ie one pass) through each entry, calling functions when their
+ time has expired. When DelayedGroupId is specified, if there are any of the specified entries
+ in the dispatch queue during dispatch, repeat the DelayedDispatch cycle.
+
+ @param DelayedDispatchTable Pointer to dispatch table
+ @param OPTIONAL DelayedGroupId used to insure particular time is met.
+
+ @return BOOLEAN
+**/
+BOOLEAN
+DelayedDispatchDispatcher (
+ IN DELAYED_DISPATCH_TABLE *DelayedDispatchTable,
+ IN EFI_GUID *DelayedGroupId OPTIONAL
+ )
+{
+ BOOLEAN Dispatched;
+ UINT64 TimeCurrent;
+ UINT64 MaxDispatchTime;
+ UINTN Index1;
+ BOOLEAN DelayedGroupIdPresent;
+ DELAYED_DISPATCH_ENTRY *Entry;
+ EFI_STATUS Status;
+
+ Dispatched = FALSE;
+ DelayedGroupIdPresent = TRUE;
+ Status = SafeUint64Add (GET_TIME_IN_US (), FixedPcdGet32 (PcdDelayedDispatchCompletionTimeoutUs), &MaxDispatchTime);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a Delay overflow\n", __func__));
+ return FALSE;
+ }
+
+ while ((DelayedDispatchTable->Count > 0) && (DelayedGroupIdPresent)) {
+ DelayedGroupIdPresent = FALSE;
+ DelayedDispatchTable->DispCount++;
+
+ // If dispatching is messed up, clear DelayedDispatchTable and exit.
+ TimeCurrent = GET_TIME_IN_US ();
+ if (TimeCurrent > MaxDispatchTime) {
+ DEBUG ((DEBUG_ERROR, "%a - DelayedDispatch Completion timeout!\n", __func__));
+ ReportStatusCode ((EFI_ERROR_MAJOR | EFI_ERROR_CODE), (EFI_SOFTWARE_PEI_CORE | EFI_SW_EC_ABORTED));
+ ASSERT (FALSE);
+ DelayedDispatchTable->Count = 0;
+ break;
+ }
+
+ // Check each entry in the table for possible dispatch
+ for (Index1 = 0; Index1 < DelayedDispatchTable->Count;) {
+ Entry = &DelayedDispatchTable->Entry[Index1];
+ // If DelayedGroupId is present, insure there is an additional check of the table.
+ if (DelayedGroupId != NULL) {
+ if (CompareGuid (DelayedGroupId, &Entry->DelayedGroupId)) {
+ DelayedGroupIdPresent = TRUE;
+ }
+ }
+
+ TimeCurrent = GET_TIME_IN_US ();
+ if (TimeCurrent >= Entry->DispatchTime) {
+ // Time expired, invoked the function
+ DEBUG ((
+ DEBUG_ERROR,
+ "Delayed dispatch entry %d @ %p, Target=%d, Act=%d Disp=%d\n",
+ Index1,
+ Entry->Function,
+ Entry->DispatchTime,
+ TimeCurrent,
+ DelayedDispatchTable->DispCount
+ ));
+ Dispatched = TRUE;
+ Entry->MicrosecondDelay = 0;
+ Entry->Function (
+ &Entry->Context,
+ &Entry->MicrosecondDelay
+ );
+ DEBUG ((DEBUG_ERROR, "Delayed dispatch Function returned delay=%d\n", Entry->MicrosecondDelay));
+ if (Entry->MicrosecondDelay == 0) {
+ // NewTime = 0 = delete this entry from the table
+ DelayedDispatchTable->Count--;
+ CopyMem (Entry, Entry+1, sizeof (DELAYED_DISPATCH_ENTRY) * (DelayedDispatchTable->Count - Index1));
+ } else {
+ if (Entry->MicrosecondDelay > FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs)) {
+ DEBUG ((DEBUG_ERROR, "%a Illegal new delay %d requested\n", __func__, Entry->MicrosecondDelay));
+ ASSERT (FALSE);
+ Entry->MicrosecondDelay = FixedPcdGet32 (PcdDelayedDispatchMaxDelayUs);
+ }
+
+ // NewTime != 0 - update the time from us to Dispatch time
+ Status = SafeUint64Add (GET_TIME_IN_US (), Entry->MicrosecondDelay, &Entry->DispatchTime);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a Delay overflow, this event will likely never be fired...\n", __func__));
+ Entry->DispatchTime = MAX_UINT64;
+ }
+
+ Index1++;
+ }
+ } else {
+ Index1++;
+ }
+ }
+ }
+
+ return Dispatched;
+}
+
+/**
+ Wait on a registered Delayed Dispatch unit that has a DelayedGroupId. Continue
+ to dispatch all registered delayed dispatch entries until *ALL* entries with
+ DelayedGroupId have completed.
+
+ Example usage:
+ 1. Register a Delayed Dispatch entry with a DelayedGroupId.
+ 2. Call this function with the DelayedGroupId
+ 3. The registered function in #1 will be called after the specified delay.
+ 4. This function will wait until all entries with the DelayedGroupId have completed.
+
+ @param[in] This The Delayed Dispatch PPI pointer.
+ @param[in] DelayedGroupId Delayed dispatch request ID the caller will wait on
+
+ @retval EFI_SUCCESS The operation succeeds.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiDelayedDispatchWaitOnEvent (
+ IN EFI_DELAYED_DISPATCH_PPI *This,
+ IN EFI_GUID DelayedGroupId
+ )
+{
+ PERF_FUNCTION_BEGIN ();
+ EFI_STATUS Status;
+ DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
+
+ // Get delayed dispatch table
+ DelayedDispatchTable = GetDelayedDispatchTable ();
+ if (DelayedDispatchTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", __func__));
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ if (IsZeroGuid (&DelayedGroupId)) {
+ DEBUG ((DEBUG_ERROR, "%a Delayed Group ID is a null GUID\n", __func__));
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ DEBUG ((DEBUG_INFO, "Delayed dispatch on %g. Count=%d, DispatchCount=%d\n", &DelayedGroupId, DelayedDispatchTable->Count, DelayedDispatchTable->DispCount));
+ PERF_EVENT_SIGNAL_BEGIN (&DelayedGroupId);
+ DelayedDispatchDispatcher (DelayedDispatchTable, &DelayedGroupId);
+ PERF_EVENT_SIGNAL_END (&DelayedGroupId);
+
+ Status = EFI_SUCCESS;
+
+Exit:
+ PERF_FUNCTION_END ();
+ return Status;
+}
+
/**
+ DelayedDispatch End of PEI callback function. Insure that all of the delayed dispatch
+ entries are complete before exiting PEI.
+
+ @param[in] PeiServices - Pointer to PEI Services Table.
+ @param[in] NotifyDesc - Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi - Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS - Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PeiDelayedDispatchOnEndOfPei (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ )
+{
+ DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
+ // Get delayed dispatch table
+ DelayedDispatchTable = GetDelayedDispatchTable ();
+ if (DelayedDispatchTable == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a Unable to locate dispatch table\n", __func__));
+ return EFI_UNSUPPORTED;
+ }
+
+ PERF_INMODULE_BEGIN ("PerfDelayedDispatchEndOfPei");
+ while (DelayedDispatchTable->Count > 0) {
+ DelayedDispatchDispatcher (DelayedDispatchTable, NULL);
+ }
+
+ DEBUG ((DEBUG_ERROR, "%a Count of dispatch cycles is %d\n", __func__, DelayedDispatchTable->DispCount));
+ PERF_INMODULE_END ("PerfDelayedDispatchEndOfPei");
+
+ return EFI_SUCCESS;
+}
+
+/**
Discover all PEIMs and optional Apriori file in one FV. There is at most one
Apriori file in one FV.
@@ -347,7 +715,7 @@ PeiLoadFixAddressHook (
// Note: Here is a assumption that system memory should always be healthy even without test.
//
if ((NextResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) &&
- (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute)&(~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0))
+ (((NextResourceHob->ResourceAttribute^ResourceHob->ResourceAttribute) & (~EFI_RESOURCE_ATTRIBUTE_TESTED)) == 0))
{
//
// See if the memory range described in ResourceHob and NextResourceHob is adjacent
@@ -1196,6 +1564,11 @@ EvacuateTempRam (
DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));
//
+ // By default migrate all FVs and copy raw data
+ //
+ FvMigrationFlags = FLAGS_FV_RAW_DATA_COPY;
+
+ //
// Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.
//
Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **)&Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **)&PeiCoreFvLocationPpi);
@@ -1205,16 +1578,21 @@ EvacuateTempRam (
PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE)SecCoreData->BootFirmwareVolumeBase;
}
- for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
- if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
- CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE));
- break;
+ if (Private->PeimDispatcherReenter) {
+ //
+ // PEI_CORE should be migrated after dispatcher re-enters from main memory.
+ //
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
+ if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
+ CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE));
+ break;
+ }
}
- }
- Status = EFI_SUCCESS;
+ Status = EFI_SUCCESS;
- ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle);
+ ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle);
+ }
Hob.Raw = GetFirstGuidHob (&gEdkiiMigrationInfoGuid);
if (Hob.Raw != NULL) {
@@ -1237,10 +1615,13 @@ EvacuateTempRam (
)
{
if ((MigrationInfo == NULL) || (MigrationInfo->MigrateAll == TRUE)) {
- //
- // Migrate all FVs and copy raw data
- //
- FvMigrationFlags = FLAGS_FV_RAW_DATA_COPY;
+ if (!Private->PeimDispatcherReenter) {
+ //
+ // Migration before dispatcher reentery is supported only when gEdkiiMigrationInfoGuid
+ // HOB is built for selective FV migration.
+ //
+ return EFI_SUCCESS;
+ }
} else {
for (Index = 0; Index < MigrationInfo->ToMigrateFvCount; Index++) {
ToMigrateFvInfo = ((TO_MIGRATE_FV_INFO *)(MigrationInfo + 1)) + Index;
@@ -1253,10 +1634,18 @@ EvacuateTempRam (
}
}
- if (Index == MigrationInfo->ToMigrateFvCount) {
+ if ((Index == MigrationInfo->ToMigrateFvCount) ||
+ ((!Private->PeimDispatcherReenter) &&
+ (((FvMigrationFlags & FLAGS_FV_MIGRATE_BEFORE_PEI_CORE_REENTRY) == 0) ||
+ (FvHeader == PeiCoreFvHandle.FvHandle))))
+ {
//
// This FV is not expected to migrate
//
+ // FV should not be migrated before dispatcher reentry if any of the below condition is true:
+ // a. MigrationInfo HOB is not built with flag FLAGS_FV_MIGRATE_BEFORE_PEI_CORE_REENTRY.
+ // b. FV contains currently executing PEI Core.
+ //
continue;
}
}
@@ -1405,12 +1794,38 @@ PeiDispatcher (
EFI_PEI_FILE_HANDLE SaveCurrentFileHandle;
EFI_FV_FILE_INFO FvFileInfo;
PEI_CORE_FV_HANDLE *CoreFvHandle;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ UINT32 TableSize;
PeiServices = (CONST EFI_PEI_SERVICES **)&Private->Ps;
PeimEntryPoint = NULL;
PeimFileHandle = NULL;
EntryPoint = 0;
+ if (Private->DelayedDispatchTable == NULL) {
+ GuidHob = GetFirstGuidHob (&gEfiDelayedDispatchTableGuid);
+ if (GuidHob != NULL) {
+ Private->DelayedDispatchTable = (DELAYED_DISPATCH_TABLE *)(GET_GUID_HOB_DATA (GuidHob));
+ } else {
+ TableSize = sizeof (DELAYED_DISPATCH_TABLE) + ((DELAYED_DISPATCH_MAX_ENTRIES - 1) * sizeof (DELAYED_DISPATCH_ENTRY));
+ Private->DelayedDispatchTable = BuildGuidHob (&gEfiDelayedDispatchTableGuid, TableSize);
+ if (Private->DelayedDispatchTable != NULL) {
+ ZeroMem (Private->DelayedDispatchTable, TableSize);
+ Status = PeiServicesInstallPpi (&mDelayedDispatchDesc);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a Failed to install Delayed Dispatch PPI: %r!\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = PeiServicesNotifyPpi (&mDelayedDispatchNotifyDesc);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a Failed to notify Delayed Dispatch on End of Pei: %r!\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ }
+ }
+ }
+
if ((Private->PeiMemoryInstalled) &&
(PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
(Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
@@ -1661,6 +2076,13 @@ PeiDispatcher (
}
}
}
+
+ // Dispatch pending delalyed dispatch requests
+ if (Private->DelayedDispatchTable != NULL) {
+ if (DelayedDispatchDispatcher (Private->DelayedDispatchTable, NULL)) {
+ ProcessDispatchNotifyList (Private);
+ }
+ }
}
//
@@ -1687,7 +2109,10 @@ PeiDispatcher (
// pass. If we did not dispatch a PEIM/FV there is no point in trying again
// as it will fail the next time too (nothing has changed).
//
- } while (Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass);
+ // Also continue dispatch loop if there are outstanding delay-
+ // dispatch registrations still running.
+ } while ((Private->PeimNeedingDispatch && Private->PeimDispatchOnThisPass) ||
+ (Private->DelayedDispatchTable->Count > 0));
}
/**
diff --git a/MdeModulePkg/Core/Pei/FwVol/FwVol.c b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
index f7cc94c..04bec98 100644
--- a/MdeModulePkg/Core/Pei/FwVol/FwVol.c
+++ b/MdeModulePkg/Core/Pei/FwVol/FwVol.c
@@ -819,6 +819,10 @@ ProcessSection (
if (!IsFfs3Fv) {
DEBUG ((DEBUG_ERROR, "Found a FFS3 formatted section in a non-FFS3 formatted FV.\n"));
SectionLength = SECTION2_SIZE (Section);
+ if (SectionLength == 0) {
+ break;
+ }
+
//
// SectionLength is adjusted it is 4 byte aligned.
// Go to the next section
@@ -854,6 +858,10 @@ ProcessSection (
SectionLength = SECTION_SIZE (Section);
}
+ if (SectionLength == 0) {
+ break;
+ }
+
//
// SectionLength is adjusted it is 4 byte aligned.
// Go to the next section
@@ -991,6 +999,10 @@ ProcessSection (
SectionLength = SECTION_SIZE (Section);
}
+ if (SectionLength == 0) {
+ break;
+ }
+
//
// SectionLength is adjusted it is 4 byte aligned.
// Go to the next section
diff --git a/MdeModulePkg/Core/Pei/Hob/Hob.c b/MdeModulePkg/Core/Pei/Hob/Hob.c
index c4882a2..6d17d7c 100644
--- a/MdeModulePkg/Core/Pei/Hob/Hob.c
+++ b/MdeModulePkg/Core/Pei/Hob/Hob.c
@@ -1,7 +1,7 @@
/** @file
This module provide Hand-Off Block manipulation.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2025, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -201,10 +201,8 @@ PeiInstallSecHobData (
@param MemoryBegin - Start Memory Address.
@param MemoryLength - Length of Memory.
- @return EFI_SUCCESS Always success to initialize HOB.
-
**/
-EFI_STATUS
+VOID
PeiCoreBuildHobHandoffInfoTable (
IN EFI_BOOT_MODE BootMode,
IN EFI_PHYSICAL_ADDRESS MemoryBegin,
@@ -232,6 +230,4 @@ PeiCoreBuildHobHandoffInfoTable (
Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength;
Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd + 1);
Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
-
- return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
index 52f37c9..80b2f89 100644
--- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
+++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
@@ -555,6 +555,7 @@ PeiAllocatePages (
EFI_PHYSICAL_ADDRESS *FreeMemoryTop;
EFI_PHYSICAL_ADDRESS *FreeMemoryBottom;
UINTN RemainingPages;
+ UINTN RemainingMemory;
UINTN Granularity;
UINTN Padding;
@@ -612,10 +613,11 @@ PeiAllocatePages (
//
// Check to see if on correct boundary for the memory type.
- // If not aligned, make the allocation aligned.
+ // If not aligned, make the allocation aligned and that we are not trying to allocate page 0, which is used for
+ // null detection.
//
Padding = *(FreeMemoryTop) & (Granularity - 1);
- if ((UINTN)(*FreeMemoryTop - *FreeMemoryBottom) < Padding) {
+ if (((UINTN)(*FreeMemoryTop - *FreeMemoryBottom) < Padding) || (*(FreeMemoryTop) - Padding == 0)) {
DEBUG ((DEBUG_ERROR, "AllocatePages failed: Out of space after padding.\n"));
return EFI_OUT_OF_RESOURCES;
}
@@ -636,24 +638,18 @@ PeiAllocatePages (
//
// Verify that there is sufficient memory to satisfy the allocation.
//
- RemainingPages = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom) >> EFI_PAGE_SHIFT;
+ RemainingMemory = (UINTN)(*FreeMemoryTop - *FreeMemoryBottom);
+ RemainingPages = (UINTN)(RShiftU64 (RemainingMemory, EFI_PAGE_SHIFT));
//
- // The number of remaining pages needs to be greater than or equal to that of the request pages.
+ // The number of remaining pages needs to be greater than or equal to that of
+ // the request pages. In addition, there should be enough space left to hold a
+ // Memory Allocation HOB.
//
Pages = ALIGN_VALUE (Pages, EFI_SIZE_TO_PAGES (Granularity));
- if (RemainingPages < Pages) {
- //
- // Try to find free memory by searching memory allocation HOBs.
- //
- Status = FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
- if (!EFI_ERROR (Status)) {
- return Status;
- }
-
- DEBUG ((DEBUG_ERROR, "AllocatePages failed: No 0x%lx Pages is available.\n", (UINT64)Pages));
- DEBUG ((DEBUG_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64)RemainingPages));
- return EFI_OUT_OF_RESOURCES;
- } else {
+ if ((RemainingPages > Pages) ||
+ ((RemainingPages == Pages) &&
+ ((RemainingMemory & EFI_PAGE_MASK) >= sizeof (EFI_HOB_MEMORY_ALLOCATION))))
+ {
//
// Update the PHIT to reflect the memory usage
//
@@ -674,6 +670,18 @@ PeiAllocatePages (
);
return EFI_SUCCESS;
+ } else {
+ //
+ // Try to find free memory by searching memory allocation HOBs.
+ //
+ Status = FindFreeMemoryFromMemoryAllocationHob (MemoryType, Pages, Granularity, Memory);
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((DEBUG_ERROR, "AllocatePages failed: No 0x%lx Pages is available.\n", (UINT64)Pages));
+ DEBUG ((DEBUG_ERROR, "There is only left 0x%lx pages memory resource to be allocated.\n", (UINT64)RemainingPages));
+ return EFI_OUT_OF_RESOURCES;
}
}
@@ -862,8 +870,6 @@ PeiAllocatePool (
(UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size),
(VOID **)&Hob
);
- ASSERT_EFI_ERROR (Status);
-
if (EFI_ERROR (Status)) {
*Buffer = NULL;
} else {
diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h
index 8df0c2d..278e5a1 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/MdeModulePkg/Core/Pei/PeiMain.h
@@ -1,7 +1,7 @@
/** @file
Definition of Pei Core Structures and Services
-Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2025, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -11,6 +11,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <PiPei.h>
#include <Ppi/DxeIpl.h>
+#include <Ppi/DelayedDispatch.h>
+#include <Ppi/EndOfPeiPhase.h>
#include <Ppi/MemoryDiscovered.h>
#include <Ppi/StatusCode.h>
#include <Ppi/Reset.h>
@@ -42,10 +44,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <IndustryStandard/PeImage.h>
#include <Library/PeiServicesTablePointerLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/TimerLib.h>
+#include <Library/SafeIntLib.h>
#include <Guid/FirmwareFileSystem2.h>
#include <Guid/FirmwareFileSystem3.h>
#include <Guid/AprioriFileName.h>
#include <Guid/MigratedFvInfo.h>
+#include <Guid/DelayedDispatch.h>
///
/// It is an FFS type extension used for PeiFindFileEx. It indicates current
@@ -208,6 +213,23 @@ EFI_STATUS
#define PEI_CORE_HANDLE_SIGNATURE SIGNATURE_32('P','e','i','C')
+//
+// Converts elapsed ticks of performance counter to time in microseconds.
+// This macro converts the elapsed ticks of running performance counter to
+// time value in unit of microseconds.
+//
+// NOTE: To support Delayed Dispatch functionality, the timer ticks are required
+// to be:
+// 1. A 64bit register;
+// 2. Guaranteed to be monotonically increasing from 0;
+// 3. Not wrapped throughout the duration of a boot;
+//
+// The requirement above is set to avoid the timer overflow issue to keep the
+// Delayed Dispatch meet the PI specification with minimal change (instead of
+// implementing a control-yielding multi-threaded PEI core).
+//
+#define GET_TIME_IN_US() ((UINT32)DivU64x32(GetTimeInNanoSecond(GetPerformanceCounter ()), 1000))
+
///
/// Pei Core private data structure instance
///
@@ -308,6 +330,11 @@ struct _PEI_CORE_INSTANCE {
// Those Memory Range will be migrated into physical memory.
//
HOLE_MEMORY_DATA HoleData[HOLE_MAX_NUMBER];
+
+ //
+ // Table of delayed dispatch requests
+ //
+ DELAYED_DISPATCH_TABLE *DelayedDispatchTable;
};
///
@@ -837,10 +864,8 @@ PeiCreateHob (
@param MemoryBegin - Start Memory Address.
@param MemoryLength - Length of Memory.
- @return EFI_SUCCESS Always success to initialize HOB.
-
**/
-EFI_STATUS
+VOID
PeiCoreBuildHobHandoffInfoTable (
IN EFI_BOOT_MODE BootMode,
IN EFI_PHYSICAL_ADDRESS MemoryBegin,
@@ -2028,4 +2053,47 @@ PeiReinitializeFv (
IN PEI_CORE_INSTANCE *PrivateData
);
+/**
+ Register a callback to be called after a minimum delay has occurred.
+
+ @param[in] This Pointer to the EFI_DELAYED_DISPATCH_PPI instance
+ @param[in] Function Function to call back
+ @param[in] Context Context data
+ @param[in] DelayedGroupId Delayed dispatch request ID the caller will wait on
+ @param[in] Delay Delay interval
+
+ @retval EFI_SUCCESS Function successfully loaded
+ @retval EFI_INVALID_PARAMETER One of the Arguments is not supported
+ @retval EFI_OUT_OF_RESOURCES No more entries
+
+**/
+EFI_STATUS
+EFIAPI
+PeiDelayedDispatchRegister (
+ IN EFI_DELAYED_DISPATCH_PPI *This,
+ IN EFI_DELAYED_DISPATCH_FUNCTION Function,
+ IN UINT64 Context,
+ IN EFI_GUID *DelayedGroupId OPTIONAL,
+ IN UINT32 Delay
+ );
+
+/**
+ Wait on a registered Delayed Dispatch unit that has a DelayedGroupId. Continue
+ to dispatch all registered delayed dispatch entries until *ALL* entries with
+ DelayedGroupId have completed.
+
+ @param[in] This The Delayed Dispatch PPI pointer.
+ @param[in] DelayedGroupId 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
+
+**/
+EFI_STATUS
+EFIAPI
+PeiDelayedDispatchWaitOnEvent (
+ IN EFI_DELAYED_DISPATCH_PPI *This,
+ IN EFI_GUID DelayedGroupId
+ );
+
#endif
diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf
index 4e545dd..4cd58ee 100644
--- a/MdeModulePkg/Core/Pei/PeiMain.inf
+++ b/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -66,6 +66,8 @@
PeCoffLib
PeiServicesTablePointerLib
PcdLib
+ TimerLib
+ SafeIntLib
[Guids]
gPeiAprioriFileNameGuid ## SOMETIMES_CONSUMES ## File
@@ -79,6 +81,7 @@
gStatusCodeCallbackGuid
gEdkiiMigratedFvInfoGuid ## SOMETIMES_PRODUCES ## HOB
gEdkiiMigrationInfoGuid ## SOMETIMES_CONSUMES ## HOB
+ gEfiDelayedDispatchTableGuid ## SOMETIMES_PRODUCES ## HOB
[Ppis]
gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist
@@ -102,6 +105,8 @@
gEfiSecHobDataPpiGuid ## SOMETIMES_CONSUMES
gEfiPeiCoreFvLocationPpiGuid ## SOMETIMES_CONSUMES
gEdkiiPeiMigrateTempRamPpiGuid ## PRODUCES
+ gEfiPeiDelayedDispatchPpiGuid ## PRODUCES
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeiStackSize ## CONSUMES
@@ -114,6 +119,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs ## CONSUMES
# [BootMode]
# S3_RESUME ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
index 0e3d9a8..ff65e69 100644
--- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
+++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -282,6 +282,9 @@ PeiCore (
OldCoreData->TempFileHandles = (EFI_PEI_FILE_HANDLE *)((UINT8 *)OldCoreData->TempFileHandles - OldCoreData->HeapOffset);
}
+ // Force relocating the dispatch table
+ OldCoreData->DelayedDispatchTable = NULL;
+
//
// Fixup for PeiService's address
//
@@ -323,6 +326,21 @@ PeiCore (
//
OldCoreData->PeiMemoryInstalled = TRUE;
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ DEBUG ((DEBUG_VERBOSE, "Early Migration - PPI lists before temporary RAM evacuation:\n"));
+ DumpPpiList (OldCoreData);
+
+ //
+ // Migrate installed content from Temporary RAM to Permanent RAM at this
+ // stage when PEI core still runs from a cached location.
+ // FVs that doesn't contain PEI_CORE should be migrated here.
+ //
+ EvacuateTempRam (OldCoreData, SecCoreData);
+
+ DEBUG ((DEBUG_VERBOSE, "Early Migration - PPI lists after temporary RAM evacuation:\n"));
+ DumpPpiList (OldCoreData);
+ }
+
//
// Indicate that PeiCore reenter
//
@@ -451,6 +469,7 @@ PeiCore (
//
// Migrate installed content from Temporary RAM to Permanent RAM
+ // FVs containing PEI_CORE should be migrated here.
//
EvacuateTempRam (&PrivateData, SecCoreData);
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
index e957cb6..100e006 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.c
@@ -670,13 +670,16 @@ SmmEntryPoint (
IN CONST EFI_SMM_ENTRY_CONTEXT *SmmEntryContext
)
{
- EFI_STATUS Status;
- EFI_SMM_COMMUNICATE_HEADER *CommunicateHeader;
- BOOLEAN InLegacyBoot;
- BOOLEAN IsOverlapped;
- BOOLEAN IsOverUnderflow;
- VOID *CommunicationBuffer;
- UINTN BufferSize;
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER_V3 *CommunicateHeader;
+ EFI_SMM_COMMUNICATE_HEADER *LegacyCommunicateHeader;
+ BOOLEAN InLegacyBoot;
+ BOOLEAN IsOverlapped;
+ VOID *CommunicationBuffer;
+ UINTN BufferSize;
+ EFI_GUID *CommGuid;
+ VOID *CommData;
+ UINTN CommHeaderSize;
PERF_FUNCTION_BEGIN ();
@@ -730,10 +733,8 @@ SmmEntryPoint (
//
// Check for over or underflows
//
- IsOverUnderflow = EFI_ERROR (SafeUintnSub (BufferSize, OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data), &BufferSize));
-
if (!SmmIsBufferOutsideSmmValid ((UINTN)CommunicationBuffer, BufferSize) ||
- IsOverlapped || IsOverUnderflow)
+ IsOverlapped || (BufferSize < OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data)))
{
//
// If CommunicationBuffer is not in valid address scope,
@@ -744,25 +745,50 @@ SmmEntryPoint (
gSmmCorePrivate->CommunicationBuffer = NULL;
gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
} else {
- CommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
- // BufferSize was updated by the SafeUintnSub() call above.
- Status = SmiManage (
- &CommunicateHeader->HeaderGuid,
- NULL,
- CommunicateHeader->Data,
- &BufferSize
- );
+ CommGuid = &((EFI_MM_COMMUNICATE_HEADER_V3 *)CommunicationBuffer)->HeaderGuid;
+ //
+ // Check if the signature matches EFI_MM_COMMUNICATE_HEADER_V3 definition
+ //
+ if (CompareGuid (CommGuid, &gEfiMmCommunicateHeaderV3Guid)) {
+ //
+ // If so, need to make sure the size is at least the size of the header
+ //
+ if (BufferSize < sizeof (EFI_MM_COMMUNICATE_HEADER_V3)) {
+ gSmmCorePrivate->CommunicationBuffer = NULL;
+ gSmmCorePrivate->ReturnStatus = EFI_ACCESS_DENIED;
+ goto AsyncSmi;
+ }
+
+ CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommunicationBuffer;
+ CommGuid = &CommunicateHeader->MessageGuid;
+ CommData = CommunicateHeader->MessageData;
+ CommHeaderSize = sizeof (EFI_MM_COMMUNICATE_HEADER_V3);
+ } else {
+ LegacyCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *)CommunicationBuffer;
+ CommGuid = &LegacyCommunicateHeader->HeaderGuid;
+ CommData = LegacyCommunicateHeader->Data;
+ CommHeaderSize = OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
+ }
+
+ BufferSize -= CommHeaderSize;
+ Status = SmiManage (
+ CommGuid,
+ NULL,
+ CommData,
+ &BufferSize
+ );
//
// Update CommunicationBuffer, BufferSize and ReturnStatus
// Communicate service finished, reset the pointer to CommBuffer to NULL
//
- gSmmCorePrivate->BufferSize = BufferSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data);
+ gSmmCorePrivate->BufferSize = BufferSize + CommHeaderSize;
gSmmCorePrivate->CommunicationBuffer = NULL;
gSmmCorePrivate->ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
}
}
}
+AsyncSmi:
//
// Process Asynchronous SMI sources
//
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
index 75a5934..22a1048 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
@@ -120,6 +120,7 @@
gSmiHandlerProfileGuid
gEdkiiEndOfS3ResumeGuid ## SOMETIMES_PRODUCES ## GUID # Install protocol
gEdkiiS3SmmInitDoneGuid ## SOMETIMES_PRODUCES ## GUID # Install protocol
+ gEfiMmCommunicateHeaderV3Guid ## CONSUMES ## GUID # Communicate header
[UserExtensions.TianoCore."ExtraFiles"]
PiSmmCoreExtra.uni
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
index fbba868..749295b 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
@@ -11,6 +11,7 @@
#include <Protocol/SmmBase2.h>
#include <Protocol/SmmCommunication.h>
#include <Protocol/MmCommunication2.h>
+#include <Protocol/MmCommunication3.h>
#include <Protocol/SmmAccess2.h>
#include <Protocol/SmmConfiguration.h>
#include <Protocol/SmmControl2.h>
@@ -147,6 +148,37 @@ SmmCommunicationMmCommunicate2 (
);
/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_MM_COMMUNICATION3_PROTOCOL instance.
+ @param[in, out] CommBufferPhysical Physical address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+ @param[in, out] CommBufferVirtual Virtual address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER CommBufferPhysical was NULL or CommBufferVirtual was NULL.
+ @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
+ If this error is returned, the MessageLength field
+ in the CommBuffer header or the integer pointed by
+ CommSize, are updated to reflect the maximum payload
+ size the implementation can accommodate.
+ @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
+ if not omitted, are in address range that cannot be
+ accessed by the MM environment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationMmCommunicate3 (
+ IN CONST EFI_MM_COMMUNICATION3_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual
+ );
+
+/**
Event notification that is fired every time a gEfiSmmConfigurationProtocol installs.
@param Event The Event that is being processed, not used.
@@ -276,6 +308,13 @@ EFI_MM_COMMUNICATION2_PROTOCOL mMmCommunication2 = {
};
//
+// PI 1.9 MM Communication Protocol 3 instance
+//
+EFI_MM_COMMUNICATION3_PROTOCOL mMmCommunication3 = {
+ MmCommunicationMmCommunicate3
+};
+
+//
// SMM Core Private Data structure that contains the data shared between
// the SMM IPL and the SMM Core.
//
@@ -652,6 +691,140 @@ SmmCommunicationMmCommunicate2 (
}
/**
+ Communicates with a registered handler.
+
+ This function provides a service to send and receive messages from a registered UEFI service.
+
+ @param[in] This The EFI_MM_COMMUNICATION3_PROTOCOL instance.
+ @param[in, out] CommBufferPhysical Physical address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+ @param[in, out] CommBufferVirtual Virtual address of the MM communication buffer, of which content must
+ start with EFI_MM_COMMUNICATE_HEADER_V3.
+ @param[out] CommSize The size of data being returned. Zero if the handler does not wish to
+ reply with any data. This parameter is optional and may be NULL.
+
+ @retval EFI_SUCCESS The message was successfully posted.
+ @retval EFI_INVALID_PARAMETER CommBufferPhysical was NULL or CommBufferVirtual was NULL.
+ @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
+ If this error is returned, the MessageLength field
+ in the CommBuffer header or the integer pointed by
+ CommSize, are updated to reflect the maximum payload
+ size the implementation can accommodate.
+ @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
+ if not omitted, are in address range that cannot be
+ accessed by the MM environment.
+
+**/
+EFI_STATUS
+EFIAPI
+MmCommunicationMmCommunicate3 (
+ IN CONST EFI_MM_COMMUNICATION3_PROTOCOL *This,
+ IN OUT VOID *CommBufferPhysical,
+ IN OUT VOID *CommBufferVirtual
+ )
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER_V3 *CommunicateHeader;
+ BOOLEAN OldInSmm;
+ UINT64 MinCommSize;
+ UINT64 TempCommSize;
+
+ //
+ // Check parameters
+ //
+ if ((CommBufferPhysical == NULL) || (CommBufferVirtual == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBufferVirtual;
+ if (!CompareGuid (
+ &CommunicateHeader->HeaderGuid,
+ &gEfiMmCommunicateHeaderV3Guid
+ ))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = SafeUint64Add (sizeof (EFI_MM_COMMUNICATE_HEADER_V3), CommunicateHeader->MessageSize, &MinCommSize);
+ if (EFI_ERROR (Status)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // CommSize must hold the entire EFI_MM_COMMUNICATE_HEADER_V3
+ //
+ if (CommunicateHeader->BufferSize < MinCommSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If not already in SMM, then generate a Software SMI
+ //
+ if (!gSmmCorePrivate->InSmm && gSmmCorePrivate->SmmEntryPointRegistered) {
+ //
+ // Put arguments for Software SMI in gSmmCorePrivate
+ //
+ gSmmCorePrivate->CommunicationBuffer = CommBufferPhysical;
+ gSmmCorePrivate->BufferSize = (UINTN)CommunicateHeader->BufferSize;
+
+ //
+ // Generate Software SMI
+ //
+ Status = mSmmControl2->Trigger (mSmmControl2, NULL, NULL, FALSE, 0);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return gSmmCorePrivate->ReturnStatus;
+ }
+
+ //
+ // If we are in SMM, then the execution mode must be physical, which means that
+ // OS established virtual addresses can not be used. If SetVirtualAddressMap()
+ // has been called, then a direct invocation of the Software SMI is not allowed,
+ // so return EFI_INVALID_PARAMETER.
+ //
+ if (EfiGoneVirtual ()) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If we are not in SMM, don't allow call SmiManage() directly when SMRAM is closed or locked.
+ //
+ if ((!gSmmCorePrivate->InSmm) && (!mSmmAccess->OpenState || mSmmAccess->LockState)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Save current InSmm state and set InSmm state to TRUE
+ //
+ OldInSmm = gSmmCorePrivate->InSmm;
+ gSmmCorePrivate->InSmm = TRUE;
+
+ //
+ // Before SetVirtualAddressMap(), we are in SMM or SMRAM is open and unlocked, call SmiManage() directly.
+ //
+ TempCommSize = CommunicateHeader->BufferSize - sizeof (EFI_MM_COMMUNICATE_HEADER_V3);
+ Status = gSmmCorePrivate->Smst->SmiManage (
+ &CommunicateHeader->MessageGuid,
+ NULL,
+ CommunicateHeader->MessageData,
+ (UINTN *)&TempCommSize
+ );
+ TempCommSize += sizeof (EFI_MM_COMMUNICATE_HEADER_V3);
+
+ // Return the size of the buffer
+ CommunicateHeader->BufferSize = TempCommSize;
+
+ //
+ // Restore original InSmm state
+ //
+ gSmmCorePrivate->InSmm = OldInSmm;
+
+ return (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND;
+}
+
+/**
Event notification that is fired when GUIDed Event Group is signaled.
@param Event The Event that is being processed, not used.
@@ -1878,6 +2051,8 @@ SmmIplEntry (
&mSmmCommunication,
&gEfiMmCommunication2ProtocolGuid,
&mMmCommunication2,
+ &gEfiMmCommunication3ProtocolGuid,
+ &mMmCommunication3,
NULL
);
ASSERT_EFI_ERROR (Status);
diff --git a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
index ddeb39c..e983bb2 100644
--- a/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+++ b/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
@@ -52,6 +52,7 @@
gEfiSmmBase2ProtocolGuid ## PRODUCES
gEfiSmmCommunicationProtocolGuid ## PRODUCES
gEfiMmCommunication2ProtocolGuid ## PRODUCES
+ gEfiMmCommunication3ProtocolGuid ## PRODUCES
gEfiSmmAccess2ProtocolGuid ## CONSUMES
## NOTIFY
## CONSUMES
@@ -80,6 +81,7 @@
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
gLoadFixedAddressConfigurationTableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiMmCommunicateHeaderV3Guid ## SOMETIMES_CONSUMES ## UNDEFINED # MM communication v3
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c b/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
index 27da289..e48532c 100644
--- a/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
+++ b/MdeModulePkg/Core/PiSmmCore/SmiHandlerProfile.c
@@ -2,6 +2,7 @@
SMI handler profile support.
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -48,6 +49,14 @@ RegisterSmiHandlerProfileHandler (
);
/**
+ Build SMI handler profile database.
+**/
+VOID
+BuildSmiHandlerProfileDatabase (
+ VOID
+ );
+
+/**
Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
into system memory with the PE/COFF Loader Library functions.
@@ -495,6 +504,8 @@ SmmReadyToLockInSmiHandlerProfile (
IN EFI_HANDLE Handle
)
{
+ RegisterSmiHandlerProfileHandler ();
+
//
// Dump all image
//
@@ -528,7 +539,7 @@ SmmReadyToLockInSmiHandlerProfile (
DEBUG ((DEBUG_INFO, "\n"));
- RegisterSmiHandlerProfileHandler ();
+ BuildSmiHandlerProfileDatabase ();
if (mImageStruct != NULL) {
FreePool (mImageStruct);
@@ -860,7 +871,7 @@ GetSmiHandlerProfileDatabaseData (
}
/**
- build SMI handler profile database.
+ Build SMI handler profile database.
**/
VOID
BuildSmiHandlerProfileDatabase (
@@ -1074,8 +1085,6 @@ RegisterSmiHandlerProfileHandler (
&DispatchHandle
);
ASSERT_EFI_ERROR (Status);
-
- BuildSmiHandlerProfileDatabase ();
}
/**
diff --git a/MdeModulePkg/Include/Guid/ArmFfaRxTxBufferInfo.h b/MdeModulePkg/Include/Guid/ArmFfaRxTxBufferInfo.h
new file mode 100644
index 0000000..0b8e2b6
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/ArmFfaRxTxBufferInfo.h
@@ -0,0 +1,31 @@
+/** @file
+ Arm FF-A ns common library Header file
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ Copyright (c), Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef ARM_FFA_RX_TX_BUFFER_INFO_H_
+#define ARM_FFA_RX_TX_BUFFER_INFO_H_
+
+/**
+ * Guid Hob Data for gArmFfaRxTxBufferInfoGuid Guid Hob.
+ */
+typedef struct ArmFfaRxTxBuffersInfo {
+ /// Tx Buffer Address.
+ VOID *TxBufferAddr;
+
+ /// Tx Buffer Size.
+ UINT64 TxBufferSize;
+
+ /// Rx Buffer Address.
+ VOID *RxBufferAddr;
+
+ /// Rx Buffer Size.
+ UINT64 RxBufferSize;
+} ARM_FFA_RX_TX_BUFFER_INFO;
+
+extern EFI_GUID gArmFfaRxTxBufferInfoGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Guid/DelayedDispatch.h b/MdeModulePkg/Include/Guid/DelayedDispatch.h
new file mode 100644
index 0000000..9be5444
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/DelayedDispatch.h
@@ -0,0 +1,47 @@
+/** @file
+ Definition for structure & defines exported by Delayed Dispatch PPI
+
+ Copyright (c), Microsoft Corporation.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef DELAYED_DISPATCH_H_
+#define DELAYED_DISPATCH_H_
+
+// Delayed Dispatch table GUID
+#define EFI_DELAYED_DISPATCH_TABLE_GUID {\
+ 0x4b733449, 0x8eff, 0x488c, { 0x92, 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07 } \
+ }
+
+//
+// Maximal number of Delayed Dispatch entries supported
+//
+#define DELAYED_DISPATCH_MAX_ENTRIES 8
+
+//
+// Internal structure for delayed dispatch entries.
+// Packing the structures here to save space as they will be stored as HOBs.
+//
+#pragma pack (push, 1)
+
+typedef struct {
+ EFI_GUID DelayedGroupId;
+ UINT64 Context;
+ EFI_DELAYED_DISPATCH_FUNCTION Function;
+ UINT64 DispatchTime;
+ UINT32 MicrosecondDelay;
+} DELAYED_DISPATCH_ENTRY;
+
+typedef struct {
+ UINT32 Count;
+ UINT32 DispCount;
+ DELAYED_DISPATCH_ENTRY Entry[DELAYED_DISPATCH_MAX_ENTRIES];
+} DELAYED_DISPATCH_TABLE;
+
+#pragma pack (pop)
+
+extern EFI_GUID gEfiDelayedDispatchTableGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Guid/MigratedFvInfo.h b/MdeModulePkg/Include/Guid/MigratedFvInfo.h
index 255e278..99681fb 100644
--- a/MdeModulePkg/Include/Guid/MigratedFvInfo.h
+++ b/MdeModulePkg/Include/Guid/MigratedFvInfo.h
@@ -18,7 +18,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// 1: FV raw data will be copied to permanent memory for later phase use (such as
// FV measurement).
//
-#define FLAGS_FV_RAW_DATA_COPY BIT0
+#define FLAGS_FV_RAW_DATA_COPY BIT0
+#define FLAGS_FV_MIGRATE_BEFORE_PEI_CORE_REENTRY BIT1
///
/// In real use cases, not all FVs need migrate to permanent memory before TempRam tears
diff --git a/MdeModulePkg/Include/Guid/MmCommBuffer.h b/MdeModulePkg/Include/Guid/MmCommBuffer.h
new file mode 100644
index 0000000..e3484e0
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/MmCommBuffer.h
@@ -0,0 +1,66 @@
+/** @file
+ MM Communication buffer data.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MM_COMM_BUFFER_H_
+#define MM_COMM_BUFFER_H_
+
+///
+/// The GUID of the MM Communication buffer HOB.
+///
+#define MM_COMM_BUFFER_HOB_GUID \
+ { 0x6c2a2520, 0x0131, 0x4aee, { 0xa7, 0x50, 0xcc, 0x38, 0x4a, 0xac, 0xe8, 0xc6 }}
+
+///
+/// The MM communicate buffer facilitates data sharing between non-MM and MM code.
+/// The MM IPL code allocates a "fixed" runtime type memory as the MM communication buffer,
+/// and communicates its address and size to MM Core via MmCommBuffer GUIDed HOB.
+/// Here, "fixed" implies that the buffer's location remains constant throughout the boot process.
+/// Data is exchanged between the MM Communication PPI/Protocol and a software MMI handler
+/// using this fixed MM communication buffer.
+///
+typedef struct {
+ ///
+ /// The address of the 4-KiB aligned fixed MM communication buffer.
+ ///
+ EFI_PHYSICAL_ADDRESS PhysicalStart;
+
+ ///
+ /// Size of the fixed MM communication buffer, in 4KiB pages.
+ ///
+ UINT64 NumberOfPages;
+
+ ///
+ /// Point to MM_COMM_BUFFER_STATUS structure.
+ ///
+ EFI_PHYSICAL_ADDRESS Status;
+} MM_COMM_BUFFER;
+
+typedef struct {
+ ///
+ /// Whether the data in the fixed MM communication buffer is valid when entering from non-MM to MM.
+ ///
+ BOOLEAN IsCommBufferValid;
+
+ /// For padding purpose
+ UINT8 Reserved[7];
+
+ ///
+ /// The return status when returning from MM to non-MM.
+ ///
+ UINT64 ReturnStatus;
+
+ ///
+ /// The size in bytes of the output buffer when returning from MM to non-MM.
+ ///
+ UINT64 ReturnBufferSize;
+} MM_COMM_BUFFER_STATUS;
+
+extern EFI_GUID gMmCommBufferHobGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Guid/NVMeEventGroup.h b/MdeModulePkg/Include/Guid/NVMeEventGroup.h
new file mode 100644
index 0000000..bd59b0c
--- /dev/null
+++ b/MdeModulePkg/Include/Guid/NVMeEventGroup.h
@@ -0,0 +1,16 @@
+/** @file
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef NVME_EVENT_GROUP_GUID_
+#define NVME_EVENT_GROUP_GUID_
+
+// gNVMeEnableStartEventGroupGuid is used to signal the start of enabling the NVMe controller
+extern EFI_GUID gNVMeEnableStartEventGroupGuid;
+// gNVMeEnableCompleteEventGroupGuid is used to signal that the NVMe controller enable has finished
+extern EFI_GUID gNVMeEnableCompleteEventGroupGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Guid/SmmVariableCommon.h b/MdeModulePkg/Include/Guid/SmmVariableCommon.h
index 1a1ab4f..e88645e 100644
--- a/MdeModulePkg/Include/Guid/SmmVariableCommon.h
+++ b/MdeModulePkg/Include/Guid/SmmVariableCommon.h
@@ -81,7 +81,8 @@ typedef struct {
///
/// Size of SMM communicate header, without including the payload.
///
-#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data))
+#define SMM_COMMUNICATE_HEADER_SIZE (OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data))
+#define SMM_COMMUNICATE_HEADER_SIZE_V3 (sizeof (EFI_MM_COMMUNICATE_HEADER_V3))
///
/// Size of SMM variable communicate header, without including the payload.
diff --git a/MdeModulePkg/Include/Library/BootLogoLib.h b/MdeModulePkg/Include/Library/BootLogoLib.h
index 2d6209a..a2fd667 100644
--- a/MdeModulePkg/Include/Library/BootLogoLib.h
+++ b/MdeModulePkg/Include/Library/BootLogoLib.h
@@ -26,7 +26,7 @@ BootLogoEnableLogo (
Use SystemTable ConOut to turn on video based Simple Text Out consoles. The
Simple Text Out screens will now be synced up with all non-video output devices.
- @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
+ @retval EFI_SUCCESS Devices are back in text mode and synced up.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Include/Library/CapsuleLib.h b/MdeModulePkg/Include/Library/CapsuleLib.h
index 92904eb..048ac32 100644
--- a/MdeModulePkg/Include/Library/CapsuleLib.h
+++ b/MdeModulePkg/Include/Library/CapsuleLib.h
@@ -24,7 +24,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
@param CapsuleHeader Pointer to the UEFI capsule image to be checked.
- @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_SUCCESS Input capsule is supported by firmware.
@retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
**/
EFI_STATUS
@@ -41,7 +41,7 @@ SupportCapsuleImage (
@param CapsuleHeader Pointer to the UEFI capsule image to be processed.
- @retval EFI_SUCESS Capsule Image processed successfully.
+ @retval EFI_SUCCESS Capsule Image processed successfully.
@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Include/Library/DebugAgentLib.h b/MdeModulePkg/Include/Library/DebugAgentLib.h
index f44bc5c..c74254e 100644
--- a/MdeModulePkg/Include/Library/DebugAgentLib.h
+++ b/MdeModulePkg/Include/Library/DebugAgentLib.h
@@ -21,6 +21,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define DEBUG_AGENT_INIT_DXE_LOAD 10
#define DEBUG_AGENT_INIT_DXE_UNLOAD 11
#define DEBUG_AGENT_INIT_THUNK_PEI_IA32TOX64 12
+#define DEBUG_AGENT_INIT_REINITIALIZE 13
+#define DEBUG_AGENT_INIT_DXE_CORE_LATE 14
//
// Context for DEBUG_AGENT_INIT_POSTMEM_SEC
diff --git a/MdeModulePkg/Include/Library/FileExplorerLib.h b/MdeModulePkg/Include/Library/FileExplorerLib.h
index 528a3ca..9159e7c 100644
--- a/MdeModulePkg/Include/Library/FileExplorerLib.h
+++ b/MdeModulePkg/Include/Library/FileExplorerLib.h
@@ -26,7 +26,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
after choose one file.
@param File Return the device path for the last time chosed file.
- @retval EFI_SUCESS Choose the file success.
+ @retval EFI_SUCCESS Choose the file success.
@retval Other errors Choose the file failed.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Include/Library/SecurityManagementLib.h b/MdeModulePkg/Include/Library/SecurityManagementLib.h
index e10a4cd..5fa1f60 100644
--- a/MdeModulePkg/Include/Library/SecurityManagementLib.h
+++ b/MdeModulePkg/Include/Library/SecurityManagementLib.h
@@ -12,7 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define __SECURITY_MANAGEMENT_LIB_H__
//
-// Authentication Operation defintions for User Identity (UID), Measured and Secure boot.
+// Authentication Operation definitions for User Identity (UID), Measured and Secure boot.
//
#define EFI_AUTH_OPERATION_NONE 0x00
#define EFI_AUTH_OPERATION_VERIFY_IMAGE 0x01
diff --git a/MdeModulePkg/Include/Library/TdxMeasurementLib.h b/MdeModulePkg/Include/Library/TdxMeasurementLib.h
new file mode 100644
index 0000000..f34318a
--- /dev/null
+++ b/MdeModulePkg/Include/Library/TdxMeasurementLib.h
@@ -0,0 +1,85 @@
+/** @file
+ TdxMeasurementLib header file
+ Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef TDX_MEASUREMENT_LIB_H
+#define TDX_MEASUREMENT_LIB_H
+
+#include <PiPei.h>
+
+#define CC_MR_INDEX_0_MRTD 0
+#define CC_MR_INDEX_1_RTMR0 1
+#define CC_MR_INDEX_2_RTMR1 2
+#define CC_MR_INDEX_3_RTMR2 3
+#define CC_MR_INDEX_INVALID 4
+
+/**
+ According to UEFI Spec 2.10 Section 38.4.1:
+ The following table shows the TPM PCR index mapping and CC event log measurement
+ register index interpretation for Intel TDX, where MRTD means Trust Domain Measurement
+ Register and RTMR means Runtime Measurement Register
+ // TPM PCR Index | CC Measurement Register Index | TDX-measurement register
+ // ------------------------------------------------------------------------
+ // 0 | 0 | MRTD
+ // 1, 7 | 1 | RTMR[0]
+ // 2~6 | 2 | RTMR[1]
+ // 8~15 | 3 | RTMR[2]
+ @param[in] PCRIndex Index of the TPM PCR
+ @retval UINT32 Index of the CC Event Log Measurement Register Index
+ @retval CC_MR_INDEX_INVALID Invalid MR Index
+**/
+UINT32
+EFIAPI
+TdxMeasurementMapPcrToMrIndex (
+ IN UINT32 PCRIndex
+ );
+
+/**
+ * Build GuidHob for Tdx CC measurement event.
+ *
+ * @param RtmrIndex RTMR index
+ * @param EventType Event type
+ * @param EventData Event data
+ * @param EventSize Size of event data
+ * @param HashValue Hash value
+ * @param HashSize Size of hash
+ *
+ * @retval EFI_SUCCESS Successfully build the GuidHobs
+ * @retval Others Other error as indicated
+ */
+EFI_STATUS
+EFIAPI
+TdxMeasurementBuildGuidHob (
+ UINT32 RtmrIndex,
+ UINT32 EventType,
+ UINT8 *EventData,
+ UINT32 EventSize,
+ UINT8 *HashValue,
+ UINT32 HashSize
+ );
+
+/**
+ * Calculate the sha384 of input Data and extend it to RTMR register.
+ *
+ * @param RtmrIndex Index of the RTMR register
+ * @param DataToHash Data to be hashed
+ * @param DataToHashLen Length of the data
+ * @param Digest Hash value of the input data
+ * @param DigestLen Length of the hash value
+ *
+ * @retval EFI_SUCCESS Successfully hash and extend to RTMR
+ * @retval Others Other errors as indicated
+ */
+EFI_STATUS
+EFIAPI
+TdxMeasurementHashAndExtendToRtmr (
+ IN UINT32 RtmrIndex,
+ IN VOID *DataToHash,
+ IN UINTN DataToHashLen,
+ OUT UINT8 *Digest,
+ IN UINTN DigestLen
+ );
+
+#endif
diff --git a/MdeModulePkg/Include/Ppi/AtaPassThru.h b/MdeModulePkg/Include/Ppi/AtaPassThru.h
index 73fb688..d0e05ae 100644
--- a/MdeModulePkg/Include/Ppi/AtaPassThru.h
+++ b/MdeModulePkg/Include/Ppi/AtaPassThru.h
@@ -141,6 +141,10 @@ EFI_STATUS
If PortMultiplierPort is the port multiplier port number of the last ATA device
on the port of the ATA controller, then EFI_NOT_FOUND is returned.
+ When port multiplier is not connected to the Port, GetNextDevice() may either return
+ EFI_SUCCESS and set PortMultiplierPort to 0xFFFF or return EFI_NOT_FOUND (in which case the
+ PortMultiplierPort value is undefined).
+
@param[in] This The PPI instance pointer.
@param[in] Port The port number present on the ATA controller.
@param[in,out] PortMultiplierPort On input, a pointer to the port multiplier
diff --git a/MdeModulePkg/Include/Ppi/UfsHostControllerPlatformPpi.h b/MdeModulePkg/Include/Ppi/UfsHostControllerPlatformPpi.h
new file mode 100644
index 0000000..9384a4e
--- /dev/null
+++ b/MdeModulePkg/Include/Ppi/UfsHostControllerPlatformPpi.h
@@ -0,0 +1,97 @@
+/** @file
+ EDKII_UFS_HC_PLATFORM_PPI definition.
+
+Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EDKII_PEI_UFS_HC_PLATFORM_PPI_H_
+#define _EDKII_PEI_UFS_HC_PLATFORM_PPI_H_
+
+#define EDKII_UFS_HC_PLATFORM_PPI_VERSION 1
+
+extern EFI_GUID gEdkiiUfsHcPlatformPpiGuid;
+
+///
+/// Forward declaration for the UFS_HOST_CONTROLLER_PPI.
+///
+typedef struct _EDKII_UFS_HC_PLATFORM_PPI EDKII_UFS_HC_PLATFORM_PPI;
+
+typedef struct {
+ UINT32 Capabilities;
+ UINT32 Version;
+} EDKII_UFS_HC_INFO;
+
+/**
+ Allows platform PPI to override host controller information
+
+ @param[in] ControllerHandle Handle of the UFS controller.
+ @param[in, out] HcInfo Pointer EDKII_UFS_HC_INFO associated with host controller.
+
+ @retval EFI_SUCCESS Function completed successfully.
+ @retval EFI_INVALID_PARAMETER HcInfo is NULL.
+ @retval Others Function failed to complete.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_UFS_HC_PLATFORM_OVERRIDE_HC_INFO)(
+ IN EFI_HANDLE ControllerHandle,
+ IN OUT EDKII_UFS_HC_INFO *HcInfo
+ );
+
+typedef enum {
+ EdkiiUfsHcPreHce,
+ EdkiiUfsHcPostHce,
+ EdkiiUfsHcPreLinkStartup,
+ EdkiiUfsHcPostLinkStartup
+} EDKII_UFS_HC_PLATFORM_CALLBACK_PHASE;
+
+typedef enum {
+ EdkiiUfsCardRefClkFreq19p2Mhz,
+ EdkiiUfsCardRefClkFreq26Mhz,
+ EdkiiUfsCardRefClkFreq38p4Mhz,
+ EdkiiUfsCardRefClkFreqObsolete
+} EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE;
+
+/**
+ Callback function for platform driver.
+
+ @param[in] UfsHcBaseddr The pointer to UfsHcBase address.
+ @param[in] CallbackPhase Specifies when the platform ppi is called
+
+ @retval EFI_SUCCESS Override function completed successfully.
+ @retval EFI_INVALID_PARAMETER CallbackPhase is invalid or CallbackData is NULL when phase expects valid data.
+ @retval Others Function failed to complete.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_UFS_HC_PLATFORM_PEI_CALLBACK)(
+ IN UINTN *UfsHcBaseAddr,
+ IN EDKII_UFS_HC_PLATFORM_CALLBACK_PHASE CallbackPhase
+ );
+
+///
+/// This PPI contains a set of services to interact with the UFS host controller.
+///
+struct _EDKII_UFS_HC_PLATFORM_PPI {
+ ///
+ /// Version of the PPI.
+ ///
+ UINT32 Version;
+ ///
+ /// Allows platform driver to override host controller information.
+ ///
+ EDKII_UFS_HC_PLATFORM_OVERRIDE_HC_INFO OverrideHcInfo;
+ ///
+ /// Allows platform driver to implement platform specific flows
+ /// for host controller.
+ ///
+ EDKII_UFS_HC_PLATFORM_PEI_CALLBACK Callback;
+ ///
+ /// Reference Clock Frequency Ufs Card Attribute that need to be set in this Ufs Host Environment.
+ ///
+ EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE RefClkFreq;
+};
+
+#endif
diff --git a/MdeModulePkg/Include/Protocol/DisplayProtocol.h b/MdeModulePkg/Include/Protocol/DisplayProtocol.h
index be08b74..79a6c9d 100644
--- a/MdeModulePkg/Include/Protocol/DisplayProtocol.h
+++ b/MdeModulePkg/Include/Protocol/DisplayProtocol.h
@@ -238,7 +238,7 @@ struct _FORM_DISPLAY_ENGINE_FORM {
//
LIST_ENTRY StatementListOSF;
//
- // The input screen dimenstions info.
+ // The input screen dimensions info.
//
EFI_SCREEN_DESCRIPTOR *ScreenDimensions;
//
diff --git a/MdeModulePkg/Include/Protocol/FileExplorer.h b/MdeModulePkg/Include/Protocol/FileExplorer.h
index aa14d27..2662a5e 100644
--- a/MdeModulePkg/Include/Protocol/FileExplorer.h
+++ b/MdeModulePkg/Include/Protocol/FileExplorer.h
@@ -48,7 +48,7 @@ BOOLEAN
after choose one file.
@param File Return the device path for the last time chosed file.
- @retval EFI_SUCESS Choose the file success.
+ @retval EFI_SUCCESS Choose the file success.
@retval Other errors Choose the file failed.
**/
typedef
diff --git a/MdeModulePkg/Include/Protocol/MediaSanitize.h b/MdeModulePkg/Include/Protocol/MediaSanitize.h
new file mode 100644
index 0000000..029b135
--- /dev/null
+++ b/MdeModulePkg/Include/Protocol/MediaSanitize.h
@@ -0,0 +1,173 @@
+/** @file
+ This file defines the Media Sanitize Protocol.
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MEDIA_SANITIZE_PROTOCOL_H_
+#define MEDIA_SANITIZE_PROTOCOL_H_
+
+#define MEDIA_SANITIZE_PROTOCOL_GUID \
+ { \
+ 0x0d799a99, 0x25af, 0x429e, { 0x92, 0x72, 0xd0, 0xb2, 0x7d, 0x6d, 0x5f, 0x14 } \
+ }
+
+typedef struct _MEDIA_SANITIZE_PROTOCOL MEDIA_SANITIZE_PROTOCOL;
+
+#define MEDIA_SANITIZE_PROTOCOL_REVISION 0x00010000
+
+///
+/// Sanitize actions for purge operation.
+///
+/// NOTE: First four actions (no action, overwrite, block erase, crypto erase) cannot
+/// be overlapped. All other fields may be overlapped as they apply.
+///
+#define PURGE_ACTION_NO_ACTION 0x00000000 // No purge action requested
+#define PURGE_ACTION_OVERWRITE 0x00000001 // Overwrite with 32-bit pattern
+#define PURGE_ACTION_BLOCK_ERASE 0x00000002 // Erase Blocks with indeterminate pattern
+#define PURGE_ACTION_CRYPTO_ERASE 0x00000004 // Delete encryption keys only
+#define PURGE_ACTION_RESET_REQUIRED 0x00000008 // Reset required after purge
+#define PURGE_ACTION_NO_DEALLOCATE 0x00000010 // Do no deallocate (trim) flash medai after sanitize
+#define PURGE_ACTION_INVERT_OW_PATTERN 0x00000020 // Invert overwrite pattern between passes
+#define PURGE_ACTION_ALLOW_UNRESTRICTED_SANITIZE_EXIT 0x00000040 // Allow exit without restrictions
+
+///
+/// Secure erase action for media format operation
+///
+#define FORMAT_SES_NO_SECURE_ERASE_REQUESTED 0x0 // No secure erase operation requested
+#define FORMAT_SES_USER_DATA_ERASE 0x1 // User Data Erase
+#define FORMAT_SES_CRYPTOGRAPHIC_ERASE 0x2 // Cryptographic Erase
+
+/**
+ Clear Media utilizes transport native WRITE commands to write a fixed pattern
+ of non-sensitive data. The size of the overwrite buffer shall be equal to the
+ one sector/LBA (in bytes).
+
+ NOTE: This function must be called from TPL aaplication or callback.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the clear request is for.
+ @param[in] PassCount Number of passes to write over the media.
+ @param[in] SectorOwBuffer Pointer to overwrite pattern buffer.
+
+ @retval EFI_SUCCESS The media clear request completed successfully
+ on the device.
+ @retval EFI_WRITE_PROTECTED The device can't be cleared due to write
+ protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to perform the clear operation.
+ @retval EFI_INVALID_PARAMETER The clear request contains parameters that
+ are not valid.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *BLOCK_MEDIA_CLEAR)(
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 PassCount,
+ IN VOID *SectorOwBuffer
+ );
+
+/**
+ Purge Media utilizes native Sanitize operations. Transport specific
+ overwrite, block erase, or crypto erase functions shall be invoked based
+ on transport.
+
+ NOTE: This function must be called from TPL aaplication or callback.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the clear request is for.
+ @param[in] PurgeAction Purge action: overwrite, crypto or block erase.
+ @param[in] OverwritePattern 32-bit pattern to overwrite on media.
+
+ @retval EFI_SUCCESS The media purge request completed successfully
+ on the device.
+ @retval EFI_WRITE_PROTECTED The device can't be purged due to write
+ protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to perform the purge operation.
+ @retval EFI_INVALID_PARAMETER The purge request contains parameters that
+ are not valid.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *BLOCK_MEDIA_PURGE)(
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 PurgeAction,
+ IN UINT32 OverwritePattern
+ );
+
+/**
+ Format Media utilizes native format operations to modify sector/LBA size.
+ Secure erase actions are used to define how latent user data is erased.
+
+ NOTE: This function must be called from TPL aaplication or callback.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the clear request is for.
+ @param[in] LbaSize Size of LBA (in terms of power of two: 2^n).
+ @param[in] SecureEraseAction Secure erase action, if any, to apply to format.
+
+ @retval EFI_SUCCESS The media format request comopleted
+ successfully on the device.
+ @retval EFI_WRITE_PROTECTED The device can't be formatted due to write
+ protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to perform the format operation.
+ @retval EFI_INVALID_PARAMETER The format request contains parameters that
+ are not valid.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+
+ **/
+typedef
+EFI_STATUS
+(EFIAPI *BLOCK_MEDIA_FORMAT)(
+ IN MEDIA_SANITIZE_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN UINT32 LbaSize,
+ IN UINT32 SecureEraseAction
+ );
+
+///
+/// The Media Sanitize Protocol provides the ability for a device to expose
+/// sanitize functionality. This optional protocol is installed on the same handle
+/// as the EFI_BLOCK_IO_PROTOCOL or EFI_BLOCK_IO2_PROTOCOL.
+///
+struct _MEDIA_SANITIZE_PROTOCOL {
+ ///
+ /// The revision to which the MEDIA_SANITIZE_PROTOCOL adheres. All future
+ /// revisions must be backwards compatible. If a future version is not
+ /// backwards compatible, it is not the same GUID.
+ ///
+ UINT64 Revision;
+
+ ///
+ /// A pointer to the EFI_BLOCK_IO_MEDIA data for this device.
+ /// Type EFI_BLOCK_IO_MEDIA is defined in BlockIo.h.
+ ///
+ EFI_BLOCK_IO_MEDIA *Media;
+
+ ///
+ /// SanitizeCapabilities shall which sanitize operations (crypto erase, block
+ /// erase, overwrite) is supported by this Block Io device.
+ ///
+ UINT32 SanitizeCapabilities;
+
+ BLOCK_MEDIA_CLEAR MediaClear;
+ BLOCK_MEDIA_PURGE MediaPurge;
+ BLOCK_MEDIA_FORMAT MediaFormat;
+};
+
+extern EFI_GUID gMediaSanitizeProtocolGuid;
+
+#endif
diff --git a/MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h b/MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h
index 250de0b..43ccca3 100644
--- a/MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h
+++ b/MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h
@@ -28,10 +28,6 @@ typedef struct _EDKII_USB_ETHERNET_PROTOCOL EDKII_USB_ETHERNET_PROTOCOL;
#define USB_RNDIS_SUBCLASS 0x04
#define USB_RNDIS_ETHERNET_PROTOCOL 0x01
-// Type Values for the DescriptorType Field
-#define CS_INTERFACE 0x24
-#define CS_ENDPOINT 0x25
-
// Descriptor SubType in Functional Descriptors
#define HEADER_FUN_DESCRIPTOR 0x00
#define UNION_FUN_DESCRIPTOR 0x06
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c
new file mode 100644
index 0000000..3423455
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.c
@@ -0,0 +1,754 @@
+/** @file
+ Arm Ffa library common code.
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmSvcLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+#include <IndustryStandard/ArmFfaPartInfo.h>
+#include <IndustryStandard/ArmStdSmc.h>
+
+#include "ArmFfaCommon.h"
+
+BOOLEAN gFfaSupported;
+UINT16 gPartId;
+
+/**
+ Convert EFI_STATUS to FFA return code.
+
+ @param [in] Status edk2 status code.
+
+ @retval ARM_FFA_RET_* return value correspond to EFI_STATUS.
+
+**/
+UINTN
+EFIAPI
+EfiStatusToFfaStatus (
+ IN EFI_STATUS Status
+ )
+{
+ switch (Status) {
+ case EFI_SUCCESS:
+ return ARM_FFA_RET_SUCCESS;
+ case EFI_INVALID_PARAMETER:
+ return ARM_FFA_RET_INVALID_PARAMETERS;
+ case EFI_OUT_OF_RESOURCES:
+ return ARM_FFA_RET_NO_MEMORY;
+ case EFI_NO_RESPONSE:
+ return ARM_FFA_RET_BUSY;
+ case EFI_INTERRUPT_PENDING:
+ return ARM_FFA_RET_INTERRUPTED;
+ case EFI_ACCESS_DENIED:
+ return ARM_FFA_RET_DENIED;
+ case EFI_ABORTED:
+ return ARM_FFA_RET_ABORTED;
+ case EFI_NOT_FOUND:
+ return ARM_FFA_RET_NODATA;
+ case EFI_NOT_READY:
+ return ARM_FFA_RET_NOT_READY;
+ default:
+ return ARM_FFA_RET_NOT_SUPPORTED;
+ }
+}
+
+/**
+ Convert FFA return code to EFI_STATUS.
+
+ @param [in] FfaStatus Ffa return Status
+
+ @retval EFI_STATUS return value correspond EFI_STATUS to FfaStatus
+
+**/
+EFI_STATUS
+EFIAPI
+FfaStatusToEfiStatus (
+ IN UINTN FfaStatus
+ )
+{
+ switch ((UINT32)FfaStatus) {
+ case ARM_FFA_RET_SUCCESS:
+ return EFI_SUCCESS;
+ case ARM_FFA_RET_INVALID_PARAMETERS:
+ return EFI_INVALID_PARAMETER;
+ case ARM_FFA_RET_NO_MEMORY:
+ return EFI_OUT_OF_RESOURCES;
+ case ARM_FFA_RET_BUSY:
+ return EFI_NO_RESPONSE;
+ case ARM_FFA_RET_INTERRUPTED:
+ return EFI_INTERRUPT_PENDING;
+ case ARM_FFA_RET_DENIED:
+ return EFI_ACCESS_DENIED;
+ case ARM_FFA_RET_ABORTED:
+ return EFI_ABORTED;
+ case ARM_FFA_RET_NODATA:
+ return EFI_NOT_FOUND;
+ case ARM_FFA_RET_NOT_READY:
+ return EFI_NOT_READY;
+ default:
+ return EFI_UNSUPPORTED;
+ }
+}
+
+/**
+ Convert FfArgs to EFI_STATUS.
+
+ @param [in] FfaArgs Ffa arguments
+
+ @retval EFI_STATUS return value correspond EFI_STATUS to FfaStatus
+
+**/
+EFI_STATUS
+EFIAPI
+FfaArgsToEfiStatus (
+ IN ARM_FFA_ARGS *FfaArgs
+ )
+{
+ UINT32 FfaStatus;
+
+ if (FfaArgs == NULL) {
+ FfaStatus = ARM_FFA_RET_INVALID_PARAMETERS;
+ } else if (IS_FID_FFA_ERROR (FfaArgs->Arg0)) {
+ /*
+ * In case of error, the Arg0 will be set to the fid FFA_ERROR.
+ * and Error code is set in Arg2.
+ */
+ FfaStatus = FfaArgs->Arg2;
+ } else if (FfaArgs->Arg0 == ARM_FFA_RET_NOT_SUPPORTED) {
+ /*
+ * If Some FF-A ABI doesn't support, it sets ARM_FFA_RET_NOT_SUPPORTED
+ * in Arg0 and other register has no meaning.
+ * In this case, set Arg2 as ARM_FFA_RET_NOT_SUPPORTED so that
+ * FfaStatusToEfiStatus (FfaARgs.Arg2) returns proper EFI_STATUS.
+ */
+ FfaStatus = ARM_FFA_RET_NOT_SUPPORTED;
+ } else if (FfaArgs->Arg0 == ARM_FID_FFA_INTERRUPT) {
+ FfaStatus = ARM_FFA_RET_INTERRUPTED;
+ } else {
+ FfaStatus = ARM_FFA_RET_SUCCESS;
+ }
+
+ return FfaStatusToEfiStatus (FfaStatus);
+}
+
+/**
+ Trigger FF-A ABI call according to PcdFfaLibConduitSmc.
+
+ @param [in, out] FfaArgs Ffa arguments
+
+**/
+VOID
+EFIAPI
+ArmCallFfa (
+ IN OUT ARM_FFA_ARGS *FfaArgs
+ )
+{
+ if (PcdGetBool (PcdFfaLibConduitSmc)) {
+ ArmCallSmc ((ARM_SMC_ARGS *)FfaArgs);
+ } else {
+ ArmCallSvc ((ARM_SVC_ARGS *)FfaArgs);
+ }
+}
+
+/**
+ Check FF-A support or not.
+
+ @retval TRUE Supported
+ @retval FALSE Not supported
+
+**/
+BOOLEAN
+EFIAPI
+IsFfaSupported (
+ IN VOID
+ )
+{
+ return gFfaSupported;
+}
+
+/**
+ Get FF-A version.
+
+ @param [in] RequestMajorVersion Minimal request major version
+ @param [in] RequestMinorVersion Minimal request minor version
+ @param [out] CurrentMajorVersion Current major version
+ @param [out] CurrentMinorVersion Current minor version
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetVersion (
+ IN UINT16 RequestMajorVersion,
+ IN UINT16 RequestMinorVersion,
+ OUT UINT16 *CurrentMajorVersion,
+ OUT UINT16 *CurrentMinorVersion
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_VERSION;
+ FfaArgs.Arg1 = ARM_FFA_CREATE_VERSION (
+ RequestMajorVersion,
+ RequestMinorVersion
+ );
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CurrentMajorVersion != NULL) {
+ *CurrentMajorVersion = ARM_FFA_MAJOR_VERSION_GET (FfaArgs.Arg0);
+ }
+
+ if (CurrentMinorVersion != NULL) {
+ *CurrentMinorVersion = ARM_FFA_MINOR_VERSION_GET (FfaArgs.Arg0);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get FF-A features.
+
+ @param [in] Id Feature id or function id
+ @param [in] InputProperties Input properties according to Id
+ @param [out] Property1 First property.
+ @param [out] Property2 Second property.
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetFeatures (
+ IN UINT32 Id,
+ IN UINT32 InputProperties,
+ OUT UINTN *Property1,
+ OUT UINTN *Property2
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if ((Property1 == NULL) || (Property2 == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Property1 = 0x00;
+ *Property2 = 0x00;
+
+ switch (Id) {
+ case ARM_FID_FFA_RXTX_MAP_AARCH32:
+ case ARM_FID_FFA_RXTX_MAP_AARCH64:
+ if ((InputProperties != FFA_RXTX_MAP_INPUT_PROPERTY_DEFAULT)) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid Parameter for FunctionId: 0x%x", __func__, Id));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+ FfaArgs.Arg0 = ARM_FID_FFA_FEATURES;
+ FfaArgs.Arg1 = Id;
+ FfaArgs.Arg2 = InputProperties;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ switch (Id) {
+ case ARM_FID_FFA_RXTX_MAP_AARCH32:
+ case ARM_FID_FFA_RXTX_MAP_AARCH64:
+ case ARM_FFA_FEATURE_ID_NOTIFICATION_PENDING_INTERRUPT:
+ case ARM_FFA_FEATURE_ID_SCHEDULE_RECEIVER_INTERRUPT:
+ case ARM_FFA_FEATURE_ID_MANAGED_EXIT_INTERRUPT:
+ *Property1 = FfaArgs.Arg2;
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Acquire ownership of the Rx buffer.
+
+ @param [in] PartId Partition Id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxAcquire (
+ IN UINT16 PartId
+ )
+{
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RX_ACQUIRE;
+ FfaArgs.Arg1 = PartId;
+
+ ArmCallFfa (&FfaArgs);
+
+ return FfaArgsToEfiStatus (&FfaArgs);
+}
+
+/**
+ Release ownership of the Rx buffer.
+
+ @param [in] PartId Partition Id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxRelease (
+ IN UINT16 PartId
+ )
+{
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RX_RELEASE;
+ FfaArgs.Arg1 = PartId;
+
+ ArmCallFfa (&FfaArgs);
+
+ return FfaArgsToEfiStatus (&FfaArgs);
+}
+
+/**
+ Get partition or VM id.
+
+ @param [out] PartId Partition id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibPartitionIdGet (
+ OUT UINT16 *PartId
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if (PartId == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_ID_GET;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get partition id. Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ *PartId = (FfaArgs.Arg2 >> ARM_FFA_DEST_EP_SHIFT) & ARM_FFA_PARTITION_ID_MASK;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get spmc or spmd partition id.
+
+ @param [out] SpmPartId spmc/spmd partition id
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibSpmIdGet (
+ OUT UINT16 *SpmPartId
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if (SpmPartId == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_SPM_ID_GET;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get partition id. Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ *SpmPartId = (FfaArgs.Arg2 >> ARM_FFA_DEST_EP_SHIFT) & ARM_FFA_PARTITION_ID_MASK;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get Partition info.
+ If This function is called to get partition descriptors
+ (Flags isn't set with FFA_PART_INFO_FLAG_TYPE_COUNT),
+ It should call ArmFfaLibRxRelease() to release RX buffer.
+
+ @param [in] ServiceGuid Service guid.
+ @param [in] Flags If this function called to get partition desc
+ and get successfully,
+ Caller should release RX buffer by calling
+ ArmFfaLibRxRelease
+ @param [out] Count Number of partition or partition descriptor
+ @param [out] Size Size of Partition Info structure in Rx Buffer
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibPartitionInfoGet (
+ IN EFI_GUID *ServiceGuid,
+ IN UINT32 Flags,
+ OUT UINT32 *Count,
+ OUT UINT32 *Size OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ UINT64 Uuid[2];
+ UINT32 *SmcUuid;
+
+ if (Count == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((((Flags >> FFA_PART_INFO_FLAG_TYPE_SHIFT) & FFA_PART_INFO_FLAG_TYPE_MASK) !=
+ FFA_PART_INFO_FLAG_TYPE_COUNT) && (Size == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ServiceGuid != NULL) {
+ ConvertGuidToUuid (ServiceGuid, (GUID *)Uuid);
+ } else {
+ ZeroMem (Uuid, sizeof (Uuid));
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+ SmcUuid = (UINT32 *)Uuid;
+
+ FfaArgs.Arg0 = ARM_FID_FFA_PARTITION_INFO_GET;
+ FfaArgs.Arg1 = SmcUuid[0];
+ FfaArgs.Arg2 = SmcUuid[1];
+ FfaArgs.Arg3 = SmcUuid[2];
+ FfaArgs.Arg4 = SmcUuid[3];
+ FfaArgs.Arg5 = Flags;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get partition information of %g. Status: %r\n",
+ __func__,
+ (ServiceGuid != NULL) ? ServiceGuid : (EFI_GUID *)Uuid,
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ *Count = FfaArgs.Arg2;
+ if (Size != NULL) {
+ *Size = FfaArgs.Arg3;
+ }
+
+ return EFI_SUCCESS;
+
+ErrorHandler:
+ *Count = 0;
+ if (Size != NULL) {
+ *Size = 0;
+ }
+
+ return Status;
+}
+
+/**
+ Restore the context which was interrupted with FFA_INTERRUPT (EFI_INTERRUPT_PENDING).
+
+ @param [in] PartId Partition id
+ @param [in] CpuNumber Cpu number in partition
+
+ @retval EFI_SUCCESS
+ @retval Other Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRun (
+ IN UINT16 PartId,
+ IN UINT16 CpuNumber
+ )
+{
+ ARM_FFA_ARGS FfaArgs;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RUN;
+ FfaArgs.Arg1 = PACK_PARTITION_ID_INFO (PartId, CpuNumber);
+
+ ArmCallFfa (&FfaArgs);
+
+ return FfaArgsToEfiStatus (&FfaArgs);
+}
+
+/**
+ Send direct message request version 1.
+
+ @param [in] DestPartId Dest partition id
+ @param [in] Flags Message flags
+ @param [in, out] ImpDefArgs Implemented defined arguments and
+ Implemented defined return values
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibMsgSendDirectReq (
+ IN UINT16 DestPartId,
+ IN UINT32 Flags,
+ IN OUT DIRECT_MSG_ARGS *ImpDefArgs
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+
+ if ((DestPartId == gPartId) || (ImpDefArgs == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_MSG_SEND_DIRECT_REQ;
+ FfaArgs.Arg1 = PACK_PARTITION_ID_INFO (gPartId, DestPartId);
+ FfaArgs.Arg2 = Flags;
+ FfaArgs.Arg3 = ImpDefArgs->Arg0;
+ FfaArgs.Arg4 = ImpDefArgs->Arg1;
+ FfaArgs.Arg5 = ImpDefArgs->Arg2;
+ FfaArgs.Arg6 = ImpDefArgs->Arg3;
+ FfaArgs.Arg7 = ImpDefArgs->Arg4;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ImpDefArgs->Arg0 = FfaArgs.Arg3;
+ ImpDefArgs->Arg1 = FfaArgs.Arg4;
+ ImpDefArgs->Arg2 = FfaArgs.Arg5;
+ ImpDefArgs->Arg3 = FfaArgs.Arg6;
+ ImpDefArgs->Arg4 = FfaArgs.Arg7;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Send direct message request version 2.
+
+ @param [in] DestPartId Dest partition id
+ @param [in] ServiceGuid Service guid
+ @param [in, out] ImpDefArgs Implemented defined arguments and
+ Implemented defined return values
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibMsgSendDirectReq2 (
+ IN UINT16 DestPartId,
+ IN EFI_GUID *ServiceGuid,
+ IN OUT DIRECT_MSG_ARGS *ImpDefArgs
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Uuid[2];
+ ARM_FFA_ARGS FfaArgs;
+
+ /*
+ * Direct message request 2 is only supported on AArch64.
+ */
+ if (sizeof (UINTN) != sizeof (UINT64)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((DestPartId == gPartId) || (ImpDefArgs == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ServiceGuid != NULL) {
+ ConvertGuidToUuid (ServiceGuid, (GUID *)Uuid);
+ } else {
+ ZeroMem (Uuid, sizeof (Uuid));
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_MSG_SEND_DIRECT_REQ2;
+ FfaArgs.Arg1 = PACK_PARTITION_ID_INFO (gPartId, DestPartId);
+ FfaArgs.Arg2 = Uuid[0];
+ FfaArgs.Arg3 = Uuid[1];
+ FfaArgs.Arg4 = ImpDefArgs->Arg0;
+ FfaArgs.Arg5 = ImpDefArgs->Arg1;
+ FfaArgs.Arg6 = ImpDefArgs->Arg2;
+ FfaArgs.Arg7 = ImpDefArgs->Arg3;
+ FfaArgs.Arg8 = ImpDefArgs->Arg4;
+ FfaArgs.Arg9 = ImpDefArgs->Arg5;
+ FfaArgs.Arg10 = ImpDefArgs->Arg6;
+ FfaArgs.Arg11 = ImpDefArgs->Arg7;
+ FfaArgs.Arg12 = ImpDefArgs->Arg8;
+ FfaArgs.Arg13 = ImpDefArgs->Arg9;
+ FfaArgs.Arg14 = ImpDefArgs->Arg10;
+ FfaArgs.Arg15 = ImpDefArgs->Arg11;
+ FfaArgs.Arg16 = ImpDefArgs->Arg12;
+ FfaArgs.Arg17 = ImpDefArgs->Arg13;
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ImpDefArgs->Arg0 = FfaArgs.Arg4;
+ ImpDefArgs->Arg1 = FfaArgs.Arg5;
+ ImpDefArgs->Arg2 = FfaArgs.Arg6;
+ ImpDefArgs->Arg3 = FfaArgs.Arg7;
+ ImpDefArgs->Arg4 = FfaArgs.Arg8;
+ ImpDefArgs->Arg5 = FfaArgs.Arg9;
+ ImpDefArgs->Arg6 = FfaArgs.Arg10;
+ ImpDefArgs->Arg7 = FfaArgs.Arg11;
+ ImpDefArgs->Arg8 = FfaArgs.Arg12;
+ ImpDefArgs->Arg9 = FfaArgs.Arg13;
+ ImpDefArgs->Arg10 = FfaArgs.Arg14;
+ ImpDefArgs->Arg11 = FfaArgs.Arg15;
+ ImpDefArgs->Arg12 = FfaArgs.Arg16;
+ ImpDefArgs->Arg13 = FfaArgs.Arg17;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Common ArmFfaLib init.
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_UNSUPPORTED FF-A isn't supported
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibCommonInit (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT16 CurrentMajorVersion;
+ UINT16 CurrentMinorVersion;
+
+ gFfaSupported = FALSE;
+
+ Status = ArmFfaLibGetVersion (
+ ARM_FFA_MAJOR_VERSION,
+ ARM_FFA_MINOR_VERSION,
+ &CurrentMajorVersion,
+ &CurrentMinorVersion
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((ARM_FFA_MAJOR_VERSION != CurrentMajorVersion) ||
+ (ARM_FFA_MINOR_VERSION > CurrentMinorVersion))
+ {
+ DEBUG ((
+ DEBUG_INFO,
+ "Incompatible FF-A Versions.\n" \
+ "Request Version: Major=0x%x, Minor=0x%x.\n" \
+ "Current Version: Major=0x%x, Minor>=0x%x.\n",
+ ARM_FFA_MAJOR_VERSION,
+ ARM_FFA_MINOR_VERSION,
+ CurrentMajorVersion,
+ CurrentMinorVersion
+ ));
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = ArmFfaLibPartitionIdGet (&gPartId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gFfaSupported = TRUE;
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.h b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.h
new file mode 100644
index 0000000..5bb1b77
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaCommon.h
@@ -0,0 +1,52 @@
+/** @file
+ Arm FF-A ns common library Header file
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+ - spmc - Secure Partition Manager Core
+ - spmd - Secure Partition Manager Dispatcher
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#ifndef ARM_FFA_COMMON_LIB_H_
+#define ARM_FFA_COMMON_LIB_H_
+
+#include <Library/ArmFfaLib.h>
+
+extern BOOLEAN gFfaSupported;
+extern UINT16 gPartId;
+
+/**
+ Convert FfArgs to EFI_STATUS.
+
+ @param [in] FfaArgs Ffa arguments
+
+ @retval EFI_STATUS return value correspond EFI_STATUS to FfaStatus
+
+**/
+EFI_STATUS
+EFIAPI
+FfaArgsToEfiStatus (
+ IN ARM_FFA_ARGS *FfaArgs
+ );
+
+/**
+ Common ArmFfaLib Constructor.
+
+ @retval EFI_SUCCESS
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibCommonInit (
+ IN VOID
+ );
+
+#endif
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.c
new file mode 100644
index 0000000..8751f2f
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.c
@@ -0,0 +1,160 @@
+/** @file
+ Arm Ffa library code for Dxe Driver
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+
+#include <Guid/ArmFfaRxTxBufferInfo.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+STATIC EFI_EVENT mFfaExitBootServiceEvent;
+
+/**
+ Unmap RX/TX buffer on Exit Boot Service.
+
+ @param [in] Event Registered exit boot service event.
+ @param [in] Context Additional data.
+
+**/
+STATIC
+VOID
+EFIAPI
+ArmFfaLibExitBootServiceEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ ArmFfaLibRxTxUnmap ();
+}
+
+/**
+ ArmFfaLib Constructor.
+
+ @param [in] ImageHandle Image Handle
+ @param [in] SystemTable System Table
+
+ @retval EFI_SUCCESS Success
+ @retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
+ @retval EFI_OUT_OF_RESOURCES Out of memory
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaDxeLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *RxTxBufferHob;
+ ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
+
+ Status = ArmFfaLibCommonInit ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_UNSUPPORTED) {
+ /*
+ * EFI_UNSUPPORTED return from ArmFfaLibCommonInit() means
+ * FF-A interface doesn't support.
+ * However, It doesn't make failure of loading driver/library instance
+ * (i.e) ArmPkg's MmCommunication Dxe/PEI Driver uses as well as SpmMm.
+ * So If FF-A is not supported the the MmCommunication Dxe/PEI falls
+ * back to SpmMm.
+ * For this case, return EFI_SUCCESS.
+ */
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+
+ if (PcdGetBool (PcdFfaExitBootEventRegistered)) {
+ return EFI_SUCCESS;
+ }
+
+ /*
+ * If PEIM uses ArmFfaPeiLib, the Rx/Tx buffers is already mapped in PEI phase.
+ * In this case, get Rx/Tx buffer info from Hob.
+ */
+ RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
+ if (RxTxBufferHob != NULL) {
+ BufferInfo = GET_GUID_HOB_DATA (RxTxBufferHob);
+ PcdSet64S (PcdFfaTxBuffer, (UINTN)BufferInfo->TxBufferAddr);
+ PcdSet64S (PcdFfaRxBuffer, (UINTN)BufferInfo->RxBufferAddr);
+ } else {
+ Status = ArmFfaLibRxTxMap ();
+
+ /*
+ * When first Dxe instance (library or driver) which uses ArmFfaLib loaded,
+ * It already maps Rx/Tx buffer.
+ * From Next Dxe instance which uses ArmFfaLib it doesn't need to map Rx/Tx
+ * buffer again but it uses the mapped one.
+ * ArmFfaLibRxTxMap() returns EFI_ALREADY_STARTED when the Rx/Tx buffers
+ * already maps.
+ */
+ if ((Status != EFI_SUCCESS) && (Status != EFI_ALREADY_STARTED)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to Map Rx/Tx buffer. Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+ }
+
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ ArmFfaLibExitBootServiceEvent,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &mFfaExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to register ExitBootService event. Status: %r\n",
+ __func__,
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ PcdSetBoolS (PcdFfaExitBootEventRegistered, TRUE);
+
+ return EFI_SUCCESS;
+
+ErrorHandler:
+ if (RxTxBufferHob != NULL) {
+ ArmFfaLibRxTxUnmap ();
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
new file mode 100644
index 0000000..361ebf6
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Provides FF-A ABI Library used in Dxe Driver.
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmFfaDxeLib
+ FILE_GUID = e2a8e040-5346-11ef-8454-eff3c163f615
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmFfaLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ArmFfaDxeLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaRxTxMap.h
+ ArmFfaRxTxMap.c
+ ArmFfaDxeLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaRxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaExitBootEventRegistered
+
+[Guids]
+ gArmFfaRxTxBufferInfoGuid
+ gEfiEventExitBootServicesGuid
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.c
new file mode 100644
index 0000000..eb55255
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.c
@@ -0,0 +1,193 @@
+/** @file
+ Arm Ffa library code for PEI Driver
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#include <Uefi.h>
+#include <PiPei.h>
+#include <Pi/PiPeiCis.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+
+#include <Guid/ArmFfaRxTxBufferInfo.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+/**
+ Update Rx/TX buffer information.
+
+ @param BufferInfo Rx/Tx buffer information.
+
+**/
+STATIC
+VOID
+EFIAPI
+UpdateRxTxBufferInfo (
+ OUT ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo
+ )
+{
+ BufferInfo->TxBufferAddr = (VOID *)(UINTN)PcdGet64 (PcdFfaTxBuffer);
+ BufferInfo->TxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ BufferInfo->RxBufferAddr = (VOID *)(UINTN)PcdGet64 (PcdFfaRxBuffer);
+ BufferInfo->RxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+}
+
+/**
+ Notification service to be called when gEfiPeiMemoryDiscoveredPpiGuid is installed.
+ This function change reamp Rx/Tx buffer with permanent memory from
+ temporary Rx/Tx buffer.
+
+ Since, the Rx/Tx buffer is chanaged after gEfiPeiMemoryDiscoveredPpiGuid is installed,
+ the Rx/Tx buffer should be gotten in each PEIM entrypoint
+ via "ArmFfaGetRxTxBuffers()" for PEIM registered as shadow and
+ call that function always then, it always gets proper Rx/Tx buffer.
+
+ @param PeiServices Indirect reference to the PEI Services Table.
+ @param NotifyDescriptor Address of the notification descriptor data structure.
+ Type EFI_PEI_NOTIFY_DESCRIPTOR is defined above.
+ @param Ppi Address of the PPI that was installed.
+
+ @retval EFI_STATUS This function will install a PPI to PPI database.
+ The status code will be the code for (*PeiServices)->InstallPpi.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PeiServicesMemoryDiscoveredNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *RxTxBufferHob;
+ ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
+
+ RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
+ ASSERT (RxTxBufferHob != NULL);
+ BufferInfo = GET_GUID_HOB_DATA (RxTxBufferHob);
+
+ /*
+ * Temporary memory doesn't need to be free.
+ * otherwise PEI memory manager using permanent memory will be confused.
+ */
+ PcdSet64S (PcdFfaTxBuffer, 0x00);
+ PcdSet64S (PcdFfaRxBuffer, 0x00);
+
+ Status = ArmFfaLibRxTxUnmap ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = ArmFfaLibRxTxMap ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ UpdateRxTxBufferInfo (BufferInfo);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyOnPeiMemoryDiscovered = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ PeiServicesMemoryDiscoveredNotifyCallback
+};
+
+/**
+ ArmFfaLib Constructor.
+
+ @param [in] FileHandle File Handle
+ @param [in] PeiServices Pei Service Table
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaPeiLibConstructor (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+ EFI_HOB_GUID_TYPE *RxTxBufferHob;
+ ARM_FFA_RX_TX_BUFFER_INFO *BufferInfo;
+ VOID *Dummy;
+
+ Status = ArmFfaLibCommonInit ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_UNSUPPORTED) {
+ /*
+ * EFI_UNSUPPORTED return from ArmFfaLibCommonInit() means
+ * FF-A interface doesn't support.
+ * However, It doesn't make failure of loading driver/library instance
+ * (i.e) ArmPkg's MmCommunication Dxe/PEI Driver uses as well as SpmMm.
+ * So If FF-A is not supported the the MmCommunication Dxe/PEI falls
+ * back to SpmMm.
+ * For this case, return EFI_SUCCESS.
+
+ */
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+
+ RxTxBufferHob = GetFirstGuidHob (&gArmFfaRxTxBufferInfoGuid);
+ if (RxTxBufferHob == NULL) {
+ Status = ArmFfaLibRxTxMap ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BufferInfo = BuildGuidHob (
+ &gArmFfaRxTxBufferInfoGuid,
+ sizeof (ARM_FFA_RX_TX_BUFFER_INFO)
+ );
+ if (BufferInfo == NULL) {
+ ArmFfaLibRxTxUnmap ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UpdateRxTxBufferInfo (BufferInfo);
+
+ Status = (*PeiServices)->LocatePpi (
+ PeiServices,
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ 0,
+ NULL,
+ &Dummy
+ );
+ if (EFI_ERROR (Status)) {
+ Status = (*PeiServices)->NotifyPpi (PeiServices, &mNotifyOnPeiMemoryDiscovered);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf
new file mode 100644
index 0000000..53d5750
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Provides FF-A ABI Library used in PEI Driver.
+#
+# Copyright (c) 2024-2025, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArmFfaPeiLib
+ FILE_GUID = 6e21912a-5f50-11ef-a3ae-dfe665fd4fc0
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmFfaLib|PEIM
+ CONSTRUCTOR = ArmFfaPeiLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaRxTxMap.h
+ ArmFfaRxTxMap.c
+ ArmFfaPeiLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaRxBuffer
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaExitBootEventRegistered
+
+[Guids]
+ gArmFfaRxTxBufferInfoGuid
+
+[Ppis]
+ gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.c
new file mode 100644
index 0000000..37d3e80
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.c
@@ -0,0 +1,272 @@
+/** @file
+ Arm Ffa library common code.
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+/**
+ Get mapped Rx/Tx buffers.
+
+ @param [out] TxBuffer Address of TxBuffer
+ @param [out] TxBufferSize Size of TxBuffer
+ @param [out] RxBuffer Address of RxBuffer
+ @param [out] RxBufferSize Size of RxBuffer
+
+ @retval EFI_SUCCESS
+ @retval Others Error.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetRxTxBuffers (
+ OUT VOID **TxBuffer OPTIONAL,
+ OUT UINT64 *TxBufferSize OPTIONAL,
+ OUT VOID **RxBuffer OPTIONAL,
+ OUT UINT64 *RxBufferSize OPTIONAL
+ )
+{
+ UINTN TxBufferAddr;
+ UINTN RxBufferAddr;
+
+ TxBufferAddr = (UINTN)PcdGet64 (PcdFfaTxBuffer);
+ RxBufferAddr = (UINTN)PcdGet64 (PcdFfaRxBuffer);
+
+ if ((TxBufferAddr == 0x00) || (RxBufferAddr == 0x00)) {
+ return EFI_NOT_READY;
+ }
+
+ if (TxBuffer != NULL) {
+ *TxBuffer = (VOID *)TxBufferAddr;
+ }
+
+ if (TxBufferSize != NULL) {
+ *TxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ }
+
+ if (RxBuffer != NULL) {
+ *RxBuffer = (VOID *)RxBufferAddr;
+ }
+
+ if (RxBufferSize != NULL) {
+ *RxBufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Mapping Rx/Tx buffers.
+ This function is only called in ArmFfaLibConstructor because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Rx/Tx buffer already mapped.
+ @retval EFI_OUT_OF_RESOURCE Out of memory
+ @retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxMap (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ UINTN Property1;
+ UINTN Property2;
+ UINTN MinSizeAndAlign;
+ UINTN MaxSize;
+ VOID *Buffers;
+ VOID *TxBuffer;
+ VOID *RxBuffer;
+ UINT64 BufferSize;
+
+ TxBuffer = (VOID *)(UINTN)PcdGet64 (PcdFfaTxBuffer);
+ RxBuffer = (VOID *)(UINTN)PcdGet64 (PcdFfaRxBuffer);
+ BufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+
+ /*
+ * If someone already mapped Rx/Tx Buffers, return EFI_ALREADY_STARTED.
+ * return EFI_ALREADY_STARTED.
+ */
+ if ((TxBuffer != NULL) && (RxBuffer != NULL)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = ArmFfaLibGetFeatures (
+ ARM_FID_FFA_RXTX_MAP,
+ FFA_RXTX_MAP_INPUT_PROPERTY_DEFAULT,
+ &Property1,
+ &Property2
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get RX/TX buffer property... Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ MinSizeAndAlign =
+ ((Property1 >>
+ ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_SHIFT) &
+ ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_MASK);
+
+ switch (MinSizeAndAlign) {
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_4K:
+ MinSizeAndAlign = SIZE_4KB;
+ break;
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_16K:
+ MinSizeAndAlign = SIZE_16KB;
+ break;
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_64K:
+ MinSizeAndAlign = SIZE_64KB;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Invalid MinSizeAndAlign: 0x%x\n", __func__, MinSizeAndAlign));
+ return EFI_UNSUPPORTED;
+ }
+
+ MaxSize =
+ (((Property1 >>
+ ARM_FFA_BUFFER_MAXSIZE_PAGE_COUNT_SHIFT) &
+ ARM_FFA_BUFFER_MAXSIZE_PAGE_COUNT_MASK));
+
+ MaxSize = ((MaxSize == 0) ? MAX_UINTN : (MaxSize * MinSizeAndAlign));
+
+ if ((MinSizeAndAlign > (PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE)) ||
+ (MaxSize < (PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE)))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Buffer is too small! MinSize: 0x%x, MaxSize: 0x%x, PageCount: %d\n",
+ __func__,
+ MinSizeAndAlign,
+ MaxSize,
+ PcdGet64 (PcdFfaTxRxPageCount)
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffers = AllocateAlignedPages ((PcdGet64 (PcdFfaTxRxPageCount) * 2), MinSizeAndAlign);
+ if (Buffers == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TxBuffer = Buffers;
+ RxBuffer = Buffers + BufferSize;
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RXTX_MAP;
+ FfaArgs.Arg1 = (UINTN)TxBuffer;
+ FfaArgs.Arg2 = (UINTN)RxBuffer;
+
+ /*
+ * PcdFfaTxRxPageCount sets with count of EFI_PAGE_SIZE granularity
+ * But, PageCounts for Tx/Rx buffer should set with
+ * count of Tx/Rx Buffer's MinSizeAndAlign. granularity.
+ */
+ FfaArgs.Arg3 = PcdGet64 (PcdFfaTxRxPageCount) / EFI_SIZE_TO_PAGES (MinSizeAndAlign);
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to map Rx/Tx buffer. Status: %r\n",
+ __func__,
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ PcdSet64S (PcdFfaTxBuffer, (UINTN)TxBuffer);
+ PcdSet64S (PcdFfaRxBuffer, (UINTN)RxBuffer);
+
+ return EFI_SUCCESS;
+
+ErrorHandler:
+ FreeAlignedPages (Buffers, (PcdGet64 (PcdFfaTxRxPageCount) * 2));
+ TxBuffer = NULL;
+ RxBuffer = NULL;
+
+ return Status;
+}
+
+/**
+ Unmap Rx/Tx buffer.
+ This function is only called in Exit boot service because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETERS Already unregistered
+ @retval EFI_UNSUPPORTED Not supported
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxUnmap (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ VOID *Buffers;
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RXTX_UNMAP;
+ FfaArgs.Arg1 = (gPartId << ARM_FFA_SOURCE_EP_SHIFT);
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ /*
+ * Rx/Tx Buffer are allocated with continuous pages.
+ * and start address of these pages is set on PcdFfaTxBuffer.
+ * See ArmFfaLibRxTxMap().
+ */
+ Buffers = (VOID *)(UINTN)PcdGet64 (PcdFfaTxBuffer);
+ if (Buffers != NULL) {
+ FreeAlignedPages (Buffers, (PcdGet64 (PcdFfaTxRxPageCount) * 2));
+ }
+
+ PcdSet64S (PcdFfaTxBuffer, 0x00);
+ PcdSet64S (PcdFfaRxBuffer, 0x00);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.h b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.h
new file mode 100644
index 0000000..6c6bfaa
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMap.h
@@ -0,0 +1,54 @@
+/** @file
+ Arm FF-A ns common library Header file
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+ - spmc - Secure Partition Manager Core
+ - spmd - Secure Partition Manager Dispatcher
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#ifndef ARM_FFA_RX_TX_MAP_LIB_H_
+#define ARM_FFA_RX_TX_MAP_LIB_H_
+
+/**
+ Mapping Rx/Tx buffers.
+ This function is only called in ArmFfaLibConstructor because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Rx/Tx buffer already mapped in PEI phase
+ @retval EFI_OUT_OF_RESOURCE Out of memory
+ @retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxMap (
+ IN VOID
+ );
+
+/**
+ Unmap Rx/Tx buffer.
+ This function is only called in Exit boot service because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETERS Already unregistered
+ @retval EFI_UNSUPPORTED Not supported
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxUnmap (
+ IN VOID
+ );
+
+#endif
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMapStmm.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMapStmm.c
new file mode 100644
index 0000000..e7c1951
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaRxTxMapStmm.c
@@ -0,0 +1,321 @@
+/** @file
+ Arm Ffa library common code.
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile v1.3 ALP1: [https://developer.arm.com/documentation/den0077/l]
+
+**/
+#include <Uefi.h>
+#include <Pi/PiMultiPhase.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MmServicesTableLib.h>
+
+#include <IndustryStandard/ArmFfaSvc.h>
+#include <Guid/ArmFfaRxTxBufferInfo.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+EFI_HANDLE mArmFfaRxTxBufferStmmInfoHandle = NULL;
+ARM_FFA_RX_TX_BUFFER_INFO *mArmFfaRxTxBufferStmmInfo = NULL;
+
+/**
+ Get mapped Rx/Tx buffers.
+
+ @param [out] TxBuffer Address of TxBuffer
+ @param [out] TxBufferSize Size of TxBuffer
+ @param [out] RxBuffer Address of RxBuffer
+ @param [out] RxBufferSize Size of RxBuffer
+
+ @retval EFI_SUCCESS
+ @retval Others Error.
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibGetRxTxBuffers (
+ OUT VOID **TxBuffer OPTIONAL,
+ OUT UINT64 *TxBufferSize OPTIONAL,
+ OUT VOID **RxBuffer OPTIONAL,
+ OUT UINT64 *RxBufferSize OPTIONAL
+ )
+{
+ UINTN TxBufferAddr;
+ UINTN RxBufferAddr;
+
+ EFI_STATUS Status = gMmst->MmLocateProtocol (
+ &gArmFfaRxTxBufferInfoGuid,
+ NULL,
+ (VOID **)&mArmFfaRxTxBufferStmmInfo
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to locate Rx/Tx buffer protocol... Status: %r\n", __func__, Status));
+ return Status;
+ }
+
+ TxBufferAddr = (UINTN)mArmFfaRxTxBufferStmmInfo->TxBufferAddr;
+ RxBufferAddr = (UINTN)mArmFfaRxTxBufferStmmInfo->RxBufferAddr;
+
+ if ((TxBufferAddr == 0x00) || (RxBufferAddr == 0x00)) {
+ return EFI_NOT_READY;
+ }
+
+ if (TxBuffer != NULL) {
+ *TxBuffer = (VOID *)TxBufferAddr;
+ }
+
+ if (TxBufferSize != NULL) {
+ *TxBufferSize = mArmFfaRxTxBufferStmmInfo->TxBufferSize;
+ }
+
+ if (RxBuffer != NULL) {
+ *RxBuffer = (VOID *)RxBufferAddr;
+ }
+
+ if (RxBufferSize != NULL) {
+ *RxBufferSize = mArmFfaRxTxBufferStmmInfo->RxBufferSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Mapping Rx/Tx buffers.
+ This function is only called in ArmFfaLibConstructor because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Rx/Tx buffer already mapped.
+ @retval EFI_OUT_OF_RESOURCE Out of memory
+ @retval EFI_INVALID_PARAMETER Invalid alignment of Rx/Tx buffer
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxMap (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ UINTN Property1;
+ UINTN Property2;
+ UINTN MinSizeAndAlign;
+ UINTN MaxSize;
+ VOID *Buffers;
+ VOID *TxBuffer;
+ VOID *RxBuffer;
+ UINT64 BufferSize;
+
+ Status = gMmst->MmLocateProtocol (
+ &gArmFfaRxTxBufferInfoGuid,
+ NULL,
+ (VOID **)&mArmFfaRxTxBufferStmmInfo
+ );
+ if (!EFI_ERROR (Status)) {
+ // Great, we got what we need.
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = ArmFfaLibGetFeatures (
+ ARM_FID_FFA_RXTX_MAP,
+ FFA_RXTX_MAP_INPUT_PROPERTY_DEFAULT,
+ &Property1,
+ &Property2
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to get RX/TX buffer property... Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ MinSizeAndAlign =
+ ((Property1 >>
+ ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_SHIFT) &
+ ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_MASK);
+
+ switch (MinSizeAndAlign) {
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_4K:
+ MinSizeAndAlign = SIZE_4KB;
+ break;
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_16K:
+ MinSizeAndAlign = SIZE_16KB;
+ break;
+ case ARM_FFA_BUFFER_MINSIZE_AND_ALIGN_64K:
+ MinSizeAndAlign = SIZE_64KB;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Invalid MinSizeAndAlign: 0x%x\n", __func__, MinSizeAndAlign));
+ return EFI_UNSUPPORTED;
+ }
+
+ MaxSize = (Property1 >> ARM_FFA_BUFFER_MAXSIZE_PAGE_COUNT_SHIFT) &
+ ARM_FFA_BUFFER_MAXSIZE_PAGE_COUNT_MASK;
+
+ MaxSize = ((MaxSize == 0) ? MAX_UINTN : (MaxSize * MinSizeAndAlign));
+
+ if ((MinSizeAndAlign > (PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE)) ||
+ (MaxSize < (PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE)))
+ {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Buffer is too small! MinSize: 0x%x, MaxSize: 0x%x, PageCount: %d\n",
+ __func__,
+ MinSizeAndAlign,
+ MaxSize,
+ PcdGet64 (PcdFfaTxRxPageCount)
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffers = AllocateAlignedPages ((PcdGet64 (PcdFfaTxRxPageCount) * 2), MinSizeAndAlign);
+ if (Buffers == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BufferSize = PcdGet64 (PcdFfaTxRxPageCount) * EFI_PAGE_SIZE;
+ TxBuffer = Buffers;
+ RxBuffer = Buffers + BufferSize;
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RXTX_MAP;
+ FfaArgs.Arg1 = (UINTN)TxBuffer;
+ FfaArgs.Arg2 = (UINTN)RxBuffer;
+
+ /*
+ * PcdFfaTxRxPageCount sets with count of EFI_PAGE_SIZE granularity
+ * But, PageCounts for Tx/Rx buffer should set with
+ * count of Tx/Rx Buffer's MinSizeAndAlign. granularity.
+ */
+ FfaArgs.Arg3 = PcdGet64 (PcdFfaTxRxPageCount) / EFI_SIZE_TO_PAGES (MinSizeAndAlign);
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to map Rx/Tx buffer. Status: %r\n",
+ __func__,
+ Status
+ ));
+ goto ErrorHandler;
+ }
+
+ mArmFfaRxTxBufferStmmInfo = AllocateZeroPool (sizeof (ARM_FFA_RX_TX_BUFFER_INFO));
+ if (mArmFfaRxTxBufferStmmInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ErrorHandler;
+ }
+
+ mArmFfaRxTxBufferStmmInfo->TxBufferAddr = TxBuffer;
+ mArmFfaRxTxBufferStmmInfo->RxBufferAddr = RxBuffer;
+ mArmFfaRxTxBufferStmmInfo->TxBufferSize = BufferSize;
+ mArmFfaRxTxBufferStmmInfo->RxBufferSize = BufferSize;
+
+ Status = gMmst->MmInstallProtocolInterface (
+ &mArmFfaRxTxBufferStmmInfoHandle,
+ &gArmFfaRxTxBufferInfoGuid,
+ EFI_NATIVE_INTERFACE,
+ mArmFfaRxTxBufferStmmInfo
+ );
+
+ return Status;
+
+ErrorHandler:
+ FreeAlignedPages (Buffers, (PcdGet64 (PcdFfaTxRxPageCount) * 2));
+ TxBuffer = NULL;
+ RxBuffer = NULL;
+
+ return Status;
+}
+
+/**
+ Unmap Rx/Tx buffer.
+ This function is only called in Exit boot service because
+ Rx/Tx buffer is registered only once per partition.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETERS Already unregistered
+ @retval EFI_UNSUPPORTED Not supported
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaLibRxTxUnmap (
+ IN VOID
+ )
+{
+ EFI_STATUS Status;
+ ARM_FFA_ARGS FfaArgs;
+ VOID *Buffers;
+
+ if (mArmFfaRxTxBufferStmmInfoHandle == NULL) {
+ // This means that the agent tried to unmap the buffers before even know them.
+ // Let's be a nice player...
+ return EFI_UNSUPPORTED;
+ }
+
+ ZeroMem (&FfaArgs, sizeof (ARM_FFA_ARGS));
+
+ FfaArgs.Arg0 = ARM_FID_FFA_RXTX_UNMAP;
+ FfaArgs.Arg1 = (gPartId << ARM_FFA_SOURCE_EP_SHIFT);
+
+ ArmCallFfa (&FfaArgs);
+
+ Status = FfaArgsToEfiStatus (&FfaArgs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ /*
+ * Rx/Tx Buffer are allocated with continuous pages.
+ * and start address of these pages is set on PcdFfaTxBuffer.
+ * See ArmFfaLibRxTxMap().
+ */
+ Buffers = (VOID *)(UINTN)mArmFfaRxTxBufferStmmInfo->TxBufferAddr;
+ if (Buffers != NULL) {
+ FreeAlignedPages (Buffers, (EFI_SIZE_TO_PAGES (mArmFfaRxTxBufferStmmInfo->TxBufferSize) * 2));
+ }
+
+ Status = gMmst->MmUninstallProtocolInterface (
+ mArmFfaRxTxBufferStmmInfoHandle,
+ &gArmFfaRxTxBufferInfoGuid,
+ mArmFfaRxTxBufferStmmInfo
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to uninstall Rx/Tx buffer protocol... Status: %r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+ }
+
+ FreePool (mArmFfaRxTxBufferStmmInfo);
+ mArmFfaRxTxBufferStmmInfo = NULL;
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf
new file mode 100644
index 0000000..863836a
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Provides FF-A ABI Library used in StandaloneMmCore.
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = ArmFfaStandaloneMmCoreLib
+ FILE_GUID = 80d2c4dc-5f0b-11ef-bc86-43b3fb486d6d
+ MODULE_TYPE = MM_CORE_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = ArmFfaLib
+ CONSTRUCTOR = ArmFfaStandaloneMmLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaStandaloneMmLib.c
+ ArmFfaRxTxMap.h
+ ArmFfaRxTxMapStmm.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MmServicesTableLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount
+
+[Guids]
+ gArmFfaRxTxBufferInfoGuid
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.c b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.c
new file mode 100644
index 0000000..72f9a80
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.c
@@ -0,0 +1,75 @@
+/** @file
+ Arm Ffa library code for StandaloneMmCore.
+
+ Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - FF-A - Firmware Framework for Arm A-profile
+
+ @par Reference(s):
+ - Arm Firmware Framework for Arm A-Profile [https://developer.arm.com/documentation/den0077/latest]
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/ArmLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/ArmFfaLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+#include "ArmFfaCommon.h"
+#include "ArmFfaRxTxMap.h"
+
+/**
+ ArmFfaLib Constructor.
+
+ @param [in] ImageHandle The firmware allocated handle for the EFI image
+ @param [in] MmSystemTable A pointer to the Management mode System Table
+
+ @retval EFI_SUCCESS Success
+ @retval Others Error
+
+**/
+EFI_STATUS
+EFIAPI
+ArmFfaStandaloneMmLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = ArmFfaLibCommonInit ();
+ if (Status == EFI_UNSUPPORTED) {
+ /*
+ * EFI_UNSUPPORTED means FF-A interface isn't available.
+ * However, for Standalone MM modules, FF-A availability is not required.
+ * i.e. Standalone MM could use SpmMm as a legitimate protocol.
+ * Thus, returning EFI_SUCCESS here to avoid the entrypoint to assert.
+ */
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed. Status = %r\n", __func__, Status));
+ }
+
+ Status = ArmFfaLibRxTxMap ();
+ if (Status == EFI_ALREADY_STARTED) {
+ /*
+ * When first Stmm instance (most likely core) which uses ArmFfaLib loaded,
+ * It already maps Rx/Tx buffer.
+ * From Next Stmm instance which uses ArmFfaLib it doesn't need to map Rx/Tx
+ * buffer again but it uses the mapped one.
+ */
+ Status = EFI_SUCCESS;
+ } else if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed. Status = %r\n", __func__, Status));
+ }
+
+ return Status;
+}
diff --git a/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf
new file mode 100644
index 0000000..019eab3
--- /dev/null
+++ b/MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Provides FF-A ABI Library used in StandaloneMmCore.
+#
+# Copyright (c) 2024, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = ArmFfaStandaloneMmLib
+ FILE_GUID = e07db74e-6a95-11ef-97ea-c7a6149e81c9
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = ArmFfaLib
+ CONSTRUCTOR = ArmFfaStandaloneMmLibConstructor
+
+[Sources]
+ ArmFfaCommon.h
+ ArmFfaCommon.c
+ ArmFfaStandaloneMmLib.c
+ ArmFfaRxTxMap.h
+ ArmFfaRxTxMapStmm.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ArmSmcLib
+ ArmSvcLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MmServicesTableLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount
+
+[Guids]
+ gArmFfaRxTxBufferInfoGuid
+
diff --git a/MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.c b/MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.c
index 4dc73fa..0cddccd 100644
--- a/MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.c
+++ b/MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.c
@@ -534,3 +534,58 @@ BuildMemoryAllocationHob (
{
ASSERT (FALSE);
}
+
+/**
+ Returns the next instance of the memory allocation HOB with the matched GUID from
+ the starting HOB.
+
+ This function searches the first instance of a HOB from the starting HOB pointer.
+ Such HOB should satisfy two conditions:
+ Its HOB type is EFI_HOB_TYPE_MEMORY_ALLOCATION and its GUID Name equals to input Guid.
+ If there does not exist such HOB from the starting HOB pointer, it will return NULL.
+
+ If Guid is NULL, then ASSERT().
+ If HobStart is NULL, then ASSERT().
+
+ @param Guid The GUID to match with in the HOB list.
+ @param HobStart The starting HOB pointer to search from.
+
+ @retval !NULL The next instance of the Memory Allocation HOB with matched GUID from the starting HOB.
+ @retval NULL NULL is returned if the matching Memory Allocation HOB is not found.
+
+**/
+VOID *
+EFIAPI
+GetNextMemoryAllocationGuidHob (
+ IN CONST EFI_GUID *Guid,
+ IN CONST VOID *HobStart
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Search the HOB list for the Memory Allocation HOB with a matching base address
+ and set the Name GUID. If there does not exist such Memory Allocation HOB in the
+ HOB list, it will return NULL.
+
+ If Guid is NULL, then ASSERT().
+
+ @param BaseAddress BaseAddress of Memory Allocation HOB to set Name to Guid.
+ @param Guid Pointer to the GUID to set in the matching Memory Allocation GUID.
+
+ @retval !NULL The instance of the tagged Memory Allocation HOB with matched base address.
+ @return NULL NULL is returned if the matching Memory Allocation HOB is not found.
+
+**/
+VOID *
+EFIAPI
+TagMemoryAllocationHobWithGuid (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN CONST EFI_GUID *Guid
+ )
+{
+ ASSERT (FALSE);
+ return NULL;
+}
diff --git a/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c b/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
index e413cea..3739980 100644
--- a/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
+++ b/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
@@ -20,7 +20,7 @@
#include <Library/BaseLib.h>
//
-// PCI Defintions.
+// PCI Definitions.
//
#define PCI_BRIDGE_32_BIT_IO_SPACE 0x01
diff --git a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c
index 478ec2d..5beb0e0 100644
--- a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c
+++ b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.c
@@ -12,7 +12,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/GraphicsOutput.h>
#include <Protocol/SimpleTextOut.h>
#include <Protocol/PlatformLogo.h>
-#include <Protocol/UgaDraw.h>
#include <Protocol/BootLogo.h>
#include <Protocol/BootLogo2.h>
#include <Library/BaseLib.h>
@@ -47,9 +46,6 @@ BootLogoEnableLogo (
UINT32 Instance;
EFI_IMAGE_INPUT Image;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
- UINT32 ColorDepth;
- UINT32 RefreshRate;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
EFI_BOOT_LOGO_PROTOCOL *BootLogo;
EDKII_BOOT_LOGO2_PROTOCOL *BootLogo2;
@@ -68,22 +64,10 @@ BootLogoEnableLogo (
return EFI_UNSUPPORTED;
}
- UgaDraw = NULL;
//
// Try to open GOP first
//
Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
- if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
- GraphicsOutput = NULL;
- //
- // Open GOP failed, try to open UGA
- //
- Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **)&UgaDraw);
- if (EFI_ERROR (Status)) {
- UgaDraw = NULL;
- }
- }
-
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
@@ -109,16 +93,8 @@ BootLogoEnableLogo (
//
gST->ConOut->EnableCursor (gST->ConOut, FALSE);
- if (GraphicsOutput != NULL) {
- SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
- SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
- } else {
- ASSERT (UgaDraw != NULL);
- Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate);
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- }
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
Blt = NULL;
NumberOfLogos = 0;
@@ -206,34 +182,18 @@ BootLogoEnableLogo (
DestY += OffsetY;
if ((DestX >= 0) && (DestY >= 0)) {
- if (GraphicsOutput != NULL) {
- Status = GraphicsOutput->Blt (
- GraphicsOutput,
- Blt,
- EfiBltBufferToVideo,
- 0,
- 0,
- (UINTN)DestX,
- (UINTN)DestY,
- Image.Width,
- Image.Height,
- Image.Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- );
- } else {
- ASSERT (UgaDraw != NULL);
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)Blt,
- EfiUgaBltBufferToVideo,
- 0,
- 0,
- (UINTN)DestX,
- (UINTN)DestY,
- Image.Width,
- Image.Height,
- Image.Width * sizeof (EFI_UGA_PIXEL)
- );
- }
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ Blt,
+ EfiBltBufferToVideo,
+ 0,
+ 0,
+ (UINTN)DestX,
+ (UINTN)DestY,
+ Image.Width,
+ Image.Height,
+ Image.Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
//
// Report displayed Logo information.
@@ -307,33 +267,18 @@ BootLogoEnableLogo (
return EFI_OUT_OF_RESOURCES;
}
- if (GraphicsOutput != NULL) {
- Status = GraphicsOutput->Blt (
- GraphicsOutput,
- LogoBlt,
- EfiBltVideoToBltBuffer,
- LogoDestX,
- LogoDestY,
- 0,
- 0,
- LogoWidth,
- LogoHeight,
- LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- );
- } else {
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)LogoBlt,
- EfiUgaVideoToBltBuffer,
- LogoDestX,
- LogoDestY,
- 0,
- 0,
- LogoWidth,
- LogoHeight,
- LogoWidth * sizeof (EFI_UGA_PIXEL)
- );
- }
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ LogoBlt,
+ EfiBltVideoToBltBuffer,
+ LogoDestX,
+ LogoDestY,
+ 0,
+ 0,
+ LogoWidth,
+ LogoHeight,
+ LogoWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
}
if (!EFI_ERROR (Status)) {
@@ -368,7 +313,7 @@ BootLogoEnableLogo (
Use SystemTable Conout to turn on video based Simple Text Out consoles. The
Simple Text Out screens will now be synced up with all non video output devices
- @retval EFI_SUCCESS UGA devices are back in text mode and synced up.
+ @retval EFI_SUCCESS GOP devices are back in text mode and synced up.
**/
EFI_STATUS
@@ -411,11 +356,8 @@ BootLogoUpdateProgress (
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
UINT32 SizeOfX;
UINT32 SizeOfY;
- UINT32 ColorDepth;
- UINT32 RefreshRate;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
UINTN BlockHeight;
UINTN BlockWidth;
@@ -428,40 +370,13 @@ BootLogoUpdateProgress (
return EFI_INVALID_PARAMETER;
}
- UgaDraw = NULL;
- Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
- if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
- GraphicsOutput = NULL;
-
- Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **)&UgaDraw);
- if (EFI_ERROR (Status)) {
- UgaDraw = NULL;
- }
- }
-
+ Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiGraphicsOutputProtocolGuid, (VOID **)&GraphicsOutput);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
- SizeOfX = 0;
- SizeOfY = 0;
- if (GraphicsOutput != NULL) {
- SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
- SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
- } else if (UgaDraw != NULL) {
- Status = UgaDraw->GetMode (
- UgaDraw,
- &SizeOfX,
- &SizeOfY,
- &ColorDepth,
- &RefreshRate
- );
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
- } else {
- return EFI_UNSUPPORTED;
- }
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
BlockWidth = SizeOfX / 100;
BlockHeight = SizeOfY / 50;
@@ -477,71 +392,37 @@ BootLogoUpdateProgress (
//
SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
- if (GraphicsOutput != NULL) {
- Status = GraphicsOutput->Blt (
- GraphicsOutput,
- &Color,
- EfiBltVideoFill,
- 0,
- 0,
- 0,
- PosY - EFI_GLYPH_HEIGHT - 1,
- SizeOfX,
- SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
- SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- );
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)&Color,
- EfiUgaVideoFill,
- 0,
- 0,
- 0,
- PosY - EFI_GLYPH_HEIGHT - 1,
- SizeOfX,
- SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
- SizeOfX * sizeof (EFI_UGA_PIXEL)
- );
- } else {
- return EFI_UNSUPPORTED;
- }
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &Color,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ PosY - EFI_GLYPH_HEIGHT - 1,
+ SizeOfX,
+ SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
}
//
// Show progress by drawing blocks
//
for (Index = PreviousValue; Index < BlockNum; Index++) {
- PosX = Index * BlockWidth;
- if (GraphicsOutput != NULL) {
- Status = GraphicsOutput->Blt (
- GraphicsOutput,
- &ProgressColor,
- EfiBltVideoFill,
- 0,
- 0,
- PosX,
- PosY,
- BlockWidth - 1,
- BlockHeight,
- (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- );
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)&ProgressColor,
- EfiUgaVideoFill,
- 0,
- 0,
- PosX,
- PosY,
- BlockWidth - 1,
- BlockHeight,
- (BlockWidth) * sizeof (EFI_UGA_PIXEL)
- );
- } else {
- return EFI_UNSUPPORTED;
- }
+ PosX = Index * BlockWidth;
+ Status = GraphicsOutput->Blt (
+ GraphicsOutput,
+ &ProgressColor,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ PosX,
+ PosY,
+ BlockWidth - 1,
+ BlockHeight,
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
}
PrintXY (
diff --git a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
index 7d50f2d..03fd704 100644
--- a/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+++ b/MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
@@ -42,11 +42,7 @@
[Protocols]
gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES
- gEfiUgaDrawProtocolGuid |PcdUgaConsumeSupport ## SOMETIMES_CONSUMES
gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiBootLogo2ProtocolGuid ## SOMETIMES_CONSUMES
gEfiUserManagerProtocolGuid ## CONSUMES
gEdkiiPlatformLogoProtocolGuid ## CONSUMES
-
-[FeaturePcd]
- gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h
index 2e9a70d..e9fc4c1 100644
--- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h
+++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManager.h
@@ -396,7 +396,7 @@ BOpt_GetBootOptions (
@param CallbackData The BMM context data.
- @return EFI_SUCESS The functin completes successfully.
+ @return EFI_SUCCESS The function completes successfully.
@retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
diff --git a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c
index e22aaf3..a47106d 100644
--- a/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c
+++ b/MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootOption.c
@@ -281,7 +281,7 @@ BOpt_FreeMenu (
@param CallbackData The BMM context data.
@return EFI_NOT_FOUND Fail to find "BootOrder" variable.
- @return EFI_SUCESS Success build boot option menu.
+ @return EFI_SUCCESS Success build boot option menu.
**/
EFI_STATUS
@@ -669,7 +669,7 @@ BOpt_GetDriverOptionNumber (
@param CallbackData The BMM context data.
- @retval EFI_SUCESS The functin completes successfully.
+ @retval EFI_SUCCESS The function completes successfully.
@retval EFI_OUT_OF_RESOURCES Not enough memory to compete the operation.
@retval EFI_NOT_FOUND Fail to get "DriverOrder" variable.
diff --git a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c
index b752679..c2232e5 100644
--- a/MdeModulePkg/Library/BootManagerUiLib/BootManager.c
+++ b/MdeModulePkg/Library/BootManagerUiLib/BootManager.c
@@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "BootManager.h"
+#include <Protocol/LoadedImage.h>
UINT16 mKeyInput;
EFI_GUID mBootManagerGuid = BOOT_MANAGER_FORMSET_GUID;
@@ -493,6 +494,9 @@ UpdateBootManager (
BOOLEAN IsLegacyOption;
BOOLEAN NeedEndOp;
UINTN MaxLen;
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
DeviceType = (UINT16)-1;
@@ -537,6 +541,25 @@ UpdateBootManager (
EndLabel->Number = LABEL_BOOT_OPTION_END;
mKeyInput = 0;
NeedEndOp = FALSE;
+
+ //
+ // Get UiApp FilePath
+ //
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+ ASSERT (DevicePath != NULL);
+
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ LoadedImage->FilePath
+ );
+
for (Index = 0; Index < BootOptionCount; Index++) {
//
// At this stage we are creating a menu entry, thus the Keys are reproduceable
@@ -551,6 +574,13 @@ UpdateBootManager (
}
//
+ // Don't display UiApp within the boot options
+ //
+ if (CompareMem (DevicePath, BootOption[Index].FilePath, GetDevicePathSize (DevicePath)) == 0) {
+ continue;
+ }
+
+ //
// Group the legacy boot option in the sub title created dynamically
//
IsLegacyOption = (BOOLEAN)(
diff --git a/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf b/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf
index 525e924..a96d553 100644
--- a/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf
+++ b/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliCustomDecompressLib.inf
@@ -1,9 +1,10 @@
## @file
# BrotliCustomDecompressLib produces BROTLI custom decompression algorithm.
#
-# It is based on the Brotli v0.5.2.
+# It is based on the Brotli v1.0.9.
# Brotli was released on the website https://github.com/google/brotli.
#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
# Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -41,6 +42,10 @@
# Wrapper header files end #
brotli/c/common/dictionary.c
brotli/c/common/transform.c
+ brotli/c/common/context.c
+ brotli/c/common/platform.c
+ brotli/c/common/constants.c
+ brotli/c/common/shared_dictionary.c
brotli/c/dec/bit_reader.c
brotli/c/dec/decode.c
brotli/c/dec/huffman.c
diff --git a/MdeModulePkg/Library/BrotliCustomDecompressLib/intrin.h b/MdeModulePkg/Library/BrotliCustomDecompressLib/intrin.h
new file mode 100644
index 0000000..7bc33be
--- /dev/null
+++ b/MdeModulePkg/Library/BrotliCustomDecompressLib/intrin.h
@@ -0,0 +1,9 @@
+/** @file
+ Include file to support building the third-party brotli.
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <BrotliDecUefiSupport.h>
diff --git a/MdeModulePkg/Library/BrotliCustomDecompressLib/memory.h b/MdeModulePkg/Library/BrotliCustomDecompressLib/memory.h
new file mode 100644
index 0000000..7bc33be
--- /dev/null
+++ b/MdeModulePkg/Library/BrotliCustomDecompressLib/memory.h
@@ -0,0 +1,9 @@
+/** @file
+ Include file to support building the third-party brotli.
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <BrotliDecUefiSupport.h>
diff --git a/MdeModulePkg/Library/BrotliCustomDecompressLib/stdio.h b/MdeModulePkg/Library/BrotliCustomDecompressLib/stdio.h
new file mode 100644
index 0000000..7bc33be
--- /dev/null
+++ b/MdeModulePkg/Library/BrotliCustomDecompressLib/stdio.h
@@ -0,0 +1,9 @@
+/** @file
+ Include file to support building the third-party brotli.
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <BrotliDecUefiSupport.h>
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c
index b3da13d..1099b64 100644
--- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.c
@@ -64,7 +64,7 @@ DisplayPageFrame (
return EFI_INVALID_PARAMETER;
}
- Status = ScreenDiemensionInfoValidate (FormData);
+ Status = ScreenDimensionInfoValidate (FormData);
if (EFI_ERROR (Status)) {
return Status;
}
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
index 58130d9..2d807bf 100644
--- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.c
@@ -378,7 +378,7 @@ ProcessExternedOpcode (
}
/**
- Validate the input screen diemenstion info.
+ Validate the input screen dimension info.
@param FormData The input form data info.
@@ -387,7 +387,7 @@ ProcessExternedOpcode (
**/
EFI_STATUS
-ScreenDiemensionInfoValidate (
+ScreenDimensionInfoValidate (
IN FORM_DISPLAY_ENGINE_FORM *FormData
)
{
@@ -598,7 +598,7 @@ PrintHotKeyHelpString (
ColumnIndex = Index % 3;
if (ColumnIndex == 0) {
CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;
- ColumnIndexWidth = ColumnWidth - 1;
+ ColumnIndexWidth = LocalScreen.RightColumn - CurrentCol - 1;
} else if (ColumnIndex == 1) {
CurrentCol = LocalScreen.LeftColumn + ColumnWidth;
ColumnIndexWidth = ColumnWidth;
@@ -646,7 +646,7 @@ PrintHotKeyHelpString (
ColumnIndex = Index % 3;
if (ColumnIndex == 0) {
CurrentCol = LocalScreen.LeftColumn + 2 * ColumnWidth;
- ColumnIndexWidth = ColumnWidth - 1;
+ ColumnIndexWidth = LocalScreen.RightColumn - CurrentCol - 1;
ColumnIndex++;
PrintStringAtWithWidth (CurrentCol, CurrentRow, gLibEmptyString, ColumnIndexWidth);
}
diff --git a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h
index 01213cb..a9ac17c 100644
--- a/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h
+++ b/MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLibInternal.h
@@ -129,7 +129,7 @@ PrintFramework (
);
/**
- Validate the input screen diemenstion info.
+ Validate the input screen dimension info.
@param FormData The input form data info.
@@ -138,7 +138,7 @@ PrintFramework (
**/
EFI_STATUS
-ScreenDiemensionInfoValidate (
+ScreenDimensionInfoValidate (
IN FORM_DISPLAY_ENGINE_FORM *FormData
);
diff --git a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c
index c8ca25e..3950bbb 100644
--- a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c
+++ b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManager.c
@@ -848,7 +848,17 @@ DeviceManagerCallback (
{
UINTN CurIndex;
- if (Action != EFI_BROWSER_ACTION_CHANGING) {
+ if (Action == EFI_BROWSER_ACTION_FORM_OPEN) {
+ //
+ // Means enter the device manager form.
+ // Update device manager page when form opens, because options may add or remove.
+ //
+ if (QuestionId == 0x1212) {
+ CreateDeviceManagerForm (DEVICE_MANAGER_FORM_ID);
+ }
+
+ return EFI_SUCCESS;
+ } else if (Action != EFI_BROWSER_ACTION_CHANGING) {
//
// Do nothing for other UEFI Action. Only do call back when data is changed.
//
@@ -926,11 +936,6 @@ DeviceManagerUiLibConstructor (
//
EfiBootManagerConnectAll ();
- //
- // Update boot manager page
- //
- CreateDeviceManagerForm (DEVICE_MANAGER_FORM_ID);
-
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr
index d81c580..911ea03 100644
--- a/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr
+++ b/MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerVfr.Vfr
@@ -28,6 +28,17 @@ formset
title = STRING_TOKEN(STR_EDKII_MENU_TITLE);
subtitle text = STRING_TOKEN(STR_DEVICES_LIST);
+ //
+ // Add this invisable text in order to indicate enter Device Manager form.
+ //
+ suppressif TRUE;
+ text
+ help = STRING_TOKEN(STR_EMPTY_STRING),
+ text = STRING_TOKEN(STR_EMPTY_STRING),
+ flags = INTERACTIVE,
+ key = 0x1212;
+ endif;
+
label LABEL_DEVICES_LIST;
label LABEL_END;
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
index 8befbae..9281322 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
@@ -10,7 +10,7 @@
ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and
performs basic validation.
- Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -49,7 +49,7 @@ EFI_EVENT mDxeCapsuleLibEndOfDxeEvent = NULL;
EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *mFmpProgress = NULL;
-BOOLEAN mDxeCapsuleLibReadyToBootEvent = FALSE;
+BOOLEAN mDxeCapsuleLibIsExitBootService = FALSE;
/**
Initialize capsule related variables.
@@ -104,7 +104,7 @@ RecordFmpCapsuleStatusVariable (
@param[in] Completion A value between 1 and 100 indicating the current
completion progress of the firmware update
- @retval EFI_SUCESS The capsule update progress was updated.
+ @retval EFI_SUCCESS The capsule update progress was updated.
@retval EFI_INVALID_PARAMETER Completion is greater than 100%.
**/
EFI_STATUS
@@ -169,6 +169,10 @@ IsValidCapsuleHeader (
IN UINT64 CapsuleSize
)
{
+ if (CapsuleHeader == NULL) {
+ return FALSE;
+ }
+
if (CapsuleHeader->CapsuleImageSize != CapsuleSize) {
return FALSE;
}
@@ -197,7 +201,7 @@ IsValidCapsuleHeader (
@param[in] CapsuleHeader Points to a capsule header.
@param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
- @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+ @retval EFI_SUCCESS Input capsule is a correct FMP capsule.
@retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
**/
EFI_STATUS
@@ -341,7 +345,7 @@ ValidateFmpCapsule (
@param[in] CapsuleHeader Points to a capsule header.
- @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_SUCCESS Input capsule is supported by firmware.
@retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
**/
EFI_STATUS
@@ -1194,7 +1198,7 @@ RecordFmpCapsuleStatus (
@param[in] CapFileName Capsule file name.
@param[out] ResetRequired Indicates whether reset is required or not.
- @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_SUCCESS Process Capsule Image successfully.
@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
@retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
@retval EFI_OUT_OF_RESOURCES Not enough memory.
@@ -1396,25 +1400,17 @@ IsNestedFmpCapsule (
EFI_SYSTEM_RESOURCE_ENTRY Entry;
EsrtGuidFound = FALSE;
- if (mEsrtTable != NULL) {
- EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);
- for (Index = 0; Index < mEsrtTable->FwResourceCount; Index++, EsrtEntry++) {
- if (CompareGuid (&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
- EsrtGuidFound = TRUE;
- break;
+ if (mDxeCapsuleLibIsExitBootService) {
+ if (mEsrtTable != NULL) {
+ EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);
+ for (Index = 0; Index < mEsrtTable->FwResourceCount; Index++, EsrtEntry++) {
+ if (CompareGuid (&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {
+ EsrtGuidFound = TRUE;
+ break;
+ }
}
}
} 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
//
@@ -1500,7 +1496,7 @@ IsFmpCapsule (
@param[in] CapsuleHeader Points to a capsule header.
- @retval EFI_SUCESS Input capsule is supported by firmware.
+ @retval EFI_SUCCESS Input capsule is supported by firmware.
@retval EFI_UNSUPPORTED Input capsule is not supported by the firmware.
@retval EFI_INVALID_PARAMETER Input capsule layout is not correct
**/
@@ -1551,7 +1547,7 @@ SupportCapsuleImage (
@param[in] CapFileName Capsule file name.
@param[out] ResetRequired Indicates whether reset is required or not.
- @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_SUCCESS Process Capsule Image successfully.
@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
@retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
@retval EFI_OUT_OF_RESOURCES Not enough memory.
@@ -1614,7 +1610,7 @@ ProcessThisCapsuleImage (
@param[in] CapsuleHeader Points to a capsule header.
- @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_SUCCESS Process Capsule Image successfully.
@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
@retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
@retval EFI_OUT_OF_RESOURCES Not enough memory.
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
index 2a38a3d..8c0023d 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c
@@ -65,7 +65,7 @@ IsFmpCapsule (
@param[in] CapsuleHeader Points to a capsule header.
@param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
- @retval EFI_SUCESS Input capsule is a correct FMP capsule.
+ @retval EFI_SUCCESS Input capsule is a correct FMP capsule.
@retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
**/
EFI_STATUS
@@ -139,7 +139,7 @@ UINT32 mCapsuleTotalNumber;
@param[in] CapFileName Capsule file name.
@param[out] ResetRequired Indicates whether reset is required or not.
- @retval EFI_SUCESS Process Capsule Image successfully.
+ @retval EFI_SUCCESS Process Capsule Image successfully.
@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.
@retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.
@retval EFI_OUT_OF_RESOURCES Not enough memory.
@@ -159,7 +159,7 @@ ProcessThisCapsuleImage (
@param[in] Completion A value between 1 and 100 indicating the current
completion progress of the firmware update
- @retval EFI_SUCESS The capsule update progress was updated.
+ @retval EFI_SUCCESS The capsule update progress was updated.
@retval EFI_INVALID_PARAMETER Completion is greater than 100%.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLibNull.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLibNull.c
index 9054ae4..9f45f27 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLibNull.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLibNull.c
@@ -18,7 +18,7 @@
@param[in] Completion A value between 1 and 100 indicating the current
completion progress of the firmware update
- @retval EFI_SUCESS The capsule update progress was updated.
+ @retval EFI_SUCCESS The capsule update progress was updated.
@retval EFI_INVALID_PARAMETER Completion is greater than 100%.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
index 855b7a6..34dc595 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
@@ -1,7 +1,7 @@
/** @file
Capsule library runtime support.
- Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -22,9 +22,10 @@
#include <Library/MemoryAllocationLib.h>
extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
+extern BOOLEAN mDxeCapsuleLibIsExitBootService;
EFI_EVENT mDxeRuntimeCapsuleLibVirtualAddressChangeEvent = NULL;
-EFI_EVENT mDxeRuntimeCapsuleLibReadyToBootEvent = NULL;
-extern BOOLEAN mDxeCapsuleLibReadyToBootEvent;
+EFI_EVENT mDxeRuntimeCapsuleLibSystemResourceTableEvent = NULL;
+EFI_EVENT mDxeRuntimeCapsuleLibExitBootServiceEvent = NULL;
/**
Convert EsrtTable physical address to virtual address.
@@ -44,16 +45,16 @@ DxeCapsuleLibVirtualAddressChangeEvent (
}
/**
- Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT.
+ Notify function for event of system resource table installation.
- @param[in] Event The Event that is being processed.
- @param[in] Context The Event Context.
+ @param[in] Event The Event that is being processed.
+ @param[in] Context The Event Context.
**/
STATIC
VOID
EFIAPI
-DxeCapsuleLibReadyToBootEventNotify (
+DxeCapsuleLibSystemResourceTableInstallEventNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
@@ -79,6 +80,14 @@ DxeCapsuleLibReadyToBootEventNotify (
//
if (Index < gST->NumberOfTableEntries) {
//
+ // Free the pool to remove the cached ESRT table.
+ //
+ if (mEsrtTable != NULL) {
+ FreePool ((VOID *)mEsrtTable);
+ mEsrtTable = NULL;
+ }
+
+ //
// Search Esrt to check given capsule is qualified
//
EsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *)ConfigEntry->VendorTable;
@@ -95,12 +104,28 @@ DxeCapsuleLibReadyToBootEventNotify (
//
mEsrtTable->FwResourceCountMax = mEsrtTable->FwResourceCount;
}
+}
+
+/**
+ Notify function for event of exit boot service.
+
+ @param[in] Event The Event that is being processed.
+ @param[in] Context The Event Context.
- mDxeCapsuleLibReadyToBootEvent = TRUE;
+**/
+STATIC
+VOID
+EFIAPI
+DxeCapsuleLibExitBootServiceEventNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ mDxeCapsuleLibIsExitBootService = TRUE;
}
/**
- The constructor function hook VirtualAddressChange event to use ESRT table as capsule routing table.
+ The constructor function for the file of DxeCapsuleRuntime.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@@ -130,15 +155,28 @@ DxeRuntimeCapsuleLibConstructor (
ASSERT_EFI_ERROR (Status);
//
- // Register notify function to cache the FMP capsule GUIDs at ReadyToBoot.
+ // Register notify function to cache the FMP capsule GUIDs when system resource table installed.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ DxeCapsuleLibSystemResourceTableInstallEventNotify,
+ NULL,
+ &gEfiSystemResourceTableGuid,
+ &mDxeRuntimeCapsuleLibSystemResourceTableEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register notify function to indicate the event is signaled at ExitBootService.
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
- DxeCapsuleLibReadyToBootEventNotify,
+ DxeCapsuleLibExitBootServiceEventNotify,
NULL,
- &gEfiEventReadyToBootGuid,
- &mDxeRuntimeCapsuleLibReadyToBootEvent
+ &gEfiEventExitBootServicesGuid,
+ &mDxeRuntimeCapsuleLibExitBootServiceEvent
);
ASSERT_EFI_ERROR (Status);
@@ -146,7 +184,7 @@ DxeRuntimeCapsuleLibConstructor (
}
/**
- The destructor function closes the VirtualAddressChange event.
+ The destructor function for the file of DxeCapsuleRuntime.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@@ -169,9 +207,15 @@ DxeRuntimeCapsuleLibDestructor (
ASSERT_EFI_ERROR (Status);
//
- // Close the ReadyToBoot event.
+ // Close the system resource table installed event.
+ //
+ Status = gBS->CloseEvent (mDxeRuntimeCapsuleLibSystemResourceTableEvent);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Close the ExitBootService event.
//
- Status = gBS->CloseEvent (mDxeRuntimeCapsuleLibReadyToBootEvent);
+ Status = gBS->CloseEvent (mDxeRuntimeCapsuleLibExitBootServiceEvent);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
index bf56f46..ef1fa57 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
@@ -3,7 +3,7 @@
#
# Capsule library instance for DXE_RUNTIME_DRIVER module types.
#
-# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -66,7 +66,7 @@
gEfiCapsuleReportGuid
gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
- gEfiEventReadyToBootGuid ## CONSUMES ## Event
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
gEdkiiCapsuleOnDiskNameGuid ## SOMETIMES_CONSUMES ## GUID
diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
index ef32771..7bf1ba7 100644
--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
+++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
@@ -21,7 +21,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Data for FPDT performance records.
//
-#define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))
+#define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE))
#define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
#define FIRMWARE_RECORD_BUFFER 0x10000
#define CACHE_HANDLE_GUID_COUNT 0x800
@@ -227,16 +227,18 @@ InternalGetSmmPerfData (
{
EFI_STATUS Status;
UINT8 *SmmBootRecordCommBuffer;
- EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader;
+ EFI_MM_COMMUNICATE_HEADER *MmCommBufferHeader;
SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
UINTN CommSize;
EFI_SMM_COMMUNICATION_PROTOCOL *Communication;
EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *SmmCommRegionTable;
EFI_MEMORY_DESCRIPTOR *SmmCommMemRegion;
UINTN Index;
+ VOID *CurrentBootRecordData;
VOID *SmmBootRecordData;
UINTN SmmBootRecordDataSize;
UINTN ReservedMemSize;
+ UINTN BootRecordDataPayloadSize;
UINTN SmmBootRecordDataRetrieved;
//
@@ -277,13 +279,13 @@ InternalGetSmmPerfData (
//
if (ReservedMemSize > SMM_BOOT_RECORD_COMM_SIZE) {
SmmBootRecordCommBuffer = (VOID *)(UINTN)SmmCommMemRegion->PhysicalStart;
- SmmCommBufferHeader = (EFI_SMM_COMMUNICATE_HEADER *)SmmBootRecordCommBuffer;
- SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE *)SmmCommBufferHeader->Data;
+ MmCommBufferHeader = (EFI_MM_COMMUNICATE_HEADER *)SmmBootRecordCommBuffer;
+ SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE *)MmCommBufferHeader->Data;
ZeroMem ((UINT8 *)SmmCommData, sizeof (SMM_BOOT_RECORD_COMMUNICATE));
- CopyGuid (&SmmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
- SmmCommBufferHeader->MessageLength = sizeof (SMM_BOOT_RECORD_COMMUNICATE);
- CommSize = SMM_BOOT_RECORD_COMM_SIZE;
+ CopyGuid (&MmCommBufferHeader->HeaderGuid, &gEfiFirmwarePerformanceGuid);
+ MmCommBufferHeader->MessageLength = sizeof (SMM_BOOT_RECORD_COMMUNICATE);
+ CommSize = SMM_BOOT_RECORD_COMM_SIZE;
//
// Get the size of boot records.
@@ -291,6 +293,11 @@ InternalGetSmmPerfData (
SmmCommData->Function = SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE;
SmmCommData->BootRecordData = NULL;
Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "Perf handler MMI not found or communicate failed. Status = %r.\n", Status));
+ } else if (EFI_ERROR (SmmCommData->ReturnStatus)) {
+ DEBUG ((DEBUG_ERROR, "Perf handler MMI returned an error. Status = %r.\n", SmmCommData->ReturnStatus));
+ }
if (!EFI_ERROR (Status) && !EFI_ERROR (SmmCommData->ReturnStatus) && (SmmCommData->BootRecordSize != 0)) {
if (SkipGetPerfData) {
@@ -307,26 +314,40 @@ InternalGetSmmPerfData (
SmmBootRecordData = AllocateZeroPool (SmmBootRecordDataSize);
SmmBootRecordDataRetrieved = 0;
ASSERT (SmmBootRecordData != NULL);
- SmmCommData->BootRecordData = (VOID *)((UINTN)SmmCommMemRegion->PhysicalStart + SMM_BOOT_RECORD_COMM_SIZE);
- SmmCommData->BootRecordSize = ReservedMemSize - SMM_BOOT_RECORD_COMM_SIZE;
- while (SmmBootRecordDataRetrieved < SmmBootRecordDataSize) {
- Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
- ASSERT_EFI_ERROR (Status);
- ASSERT_EFI_ERROR (SmmCommData->ReturnStatus);
- if (SmmBootRecordDataRetrieved + SmmCommData->BootRecordSize > SmmBootRecordDataSize) {
- CopyMem ((UINT8 *)SmmBootRecordData + SmmBootRecordDataRetrieved, SmmCommData->BootRecordData, SmmBootRecordDataSize - SmmBootRecordDataRetrieved);
- } else {
- CopyMem ((UINT8 *)SmmBootRecordData + SmmBootRecordDataRetrieved, SmmCommData->BootRecordData, SmmCommData->BootRecordSize);
+ if (SmmBootRecordData != NULL) {
+ CurrentBootRecordData = (VOID *)((UINTN)SmmCommMemRegion->PhysicalStart + SMM_BOOT_RECORD_COMM_SIZE);
+ while (SmmBootRecordDataRetrieved < SmmBootRecordDataSize) {
+ // Note: Maximum comm buffer data payload size is ReservedMemSize - SMM_BOOT_RECORD_COMM_SIZE
+ BootRecordDataPayloadSize = MIN (
+ ReservedMemSize - SMM_BOOT_RECORD_COMM_SIZE,
+ SmmBootRecordDataSize - SmmBootRecordDataRetrieved
+ );
+ SmmCommData->BootRecordSize = BootRecordDataPayloadSize;
+
+ MmCommBufferHeader->MessageLength = sizeof (SMM_BOOT_RECORD_COMMUNICATE) + BootRecordDataPayloadSize;
+ CommSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + (UINTN)MmCommBufferHeader->MessageLength;
+
+ Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize);
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status) || EFI_ERROR (SmmCommData->ReturnStatus)) {
+ break;
+ }
+
+ if (SmmBootRecordDataRetrieved + SmmCommData->BootRecordSize > SmmBootRecordDataSize) {
+ CopyMem ((UINT8 *)SmmBootRecordData + SmmBootRecordDataRetrieved, CurrentBootRecordData, SmmBootRecordDataSize - SmmBootRecordDataRetrieved);
+ } else {
+ CopyMem ((UINT8 *)SmmBootRecordData + SmmBootRecordDataRetrieved, CurrentBootRecordData, SmmCommData->BootRecordSize);
+ }
+
+ SmmBootRecordDataRetrieved += SmmCommData->BootRecordSize;
+ SmmCommData->BootRecordOffset += SmmCommData->BootRecordSize;
}
- SmmBootRecordDataRetrieved += SmmCommData->BootRecordSize;
- SmmCommData->BootRecordOffset += SmmCommData->BootRecordSize;
- }
-
- mSmmBootRecordOffset = SmmCommData->BootRecordOffset;
+ mSmmBootRecordOffset = SmmCommData->BootRecordOffset;
- *SmmPerfData = SmmBootRecordData;
- *SmmPerfDataSize = SmmBootRecordDataSize;
+ *SmmPerfData = SmmBootRecordData;
+ *SmmPerfDataSize = SmmBootRecordDataSize;
+ }
}
}
}
diff --git a/MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.c b/MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.c
index a8f07c8..28ef4df 100644
--- a/MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.c
+++ b/MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.c
@@ -68,7 +68,7 @@ FileExplorerConstructor (
after choose one file.
@param File Return the device path for the last time chosed file.
- @retval EFI_SUCESS Choose file success.
+ @retval EFI_SUCCESS Choose file success.
@retval EFI_INVALID_PARAMETER Both ChooseHandler and return device path are NULL
One of them must not NULL.
@retval Other errors Choose file failed.
diff --git a/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c b/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
index 804a03d..42ad80c 100644
--- a/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
+++ b/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
@@ -870,7 +870,7 @@ LibFindFileSystem (
@param MenuEntry Input Menu info.
@param RetFileHandle Return the file handle for the input device path.
- @retval EFI_SUCESS Find the file handle success.
+ @retval EFI_SUCCESS Find the file handle success.
@retval Other Find the file handle failure.
**/
EFI_STATUS
@@ -918,7 +918,7 @@ LibGetFileHandleFromMenu (
@param ParentFileName Parent file name.
@param DeviceHandle Driver handle for this partition.
- @retval EFI_SUCESS Find the file handle success.
+ @retval EFI_SUCCESS Find the file handle success.
@retval Other Find the file handle failure.
**/
EFI_STATUS
@@ -1478,7 +1478,7 @@ LibGetDevicePath (
after choose one file.
@param File Return the device path for the last time chosed file.
- @retval EFI_SUCESS Choose file success.
+ @retval EFI_SUCCESS Choose file success.
@retval EFI_INVALID_PARAMETER Both ChooseHandler and return device path are NULL
One of them must not NULL.
@retval Other errors Choose file failed.
diff --git a/MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf b/MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf
index a88cabf..3b366a9 100644
--- a/MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf
+++ b/MdeModulePkg/Library/HobPrintLib/HobPrintLib.inf
@@ -32,3 +32,4 @@
gEfiHobMemoryAllocBspStoreGuid
gEfiHobMemoryAllocStackGuid
gEfiMemoryTypeInformationGuid
+ gEfiHobMemoryAllocModuleGuid
diff --git a/MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.c b/MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.c
index 59b5c2b..8e9f632 100644
--- a/MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.c
+++ b/MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.c
@@ -12,8 +12,8 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
-EFI_EVENT mRuntimeResetSystemLibVirtualAddressChangeEvent;
-EFI_RUNTIME_SERVICES *mInternalRT;
+EFI_EVENT mRuntimeResetSystemLibVirtualAddressChangeEvent;
+static EFI_RUNTIME_SERVICES *mInternalRT;
/**
This function causes a system-wide reset (cold reset), in which
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/MmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/MmCorePerformanceLib.c
new file mode 100644
index 0000000..8982df0
--- /dev/null
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/MmCorePerformanceLib.c
@@ -0,0 +1,1306 @@
+/** @file
+ This library is mainly used by a MM Core to start performance logging to ensure that
+ MM Performance and PerformanceEx Protocol are installed as early as possible in the MM phase.
+
+ Caution: This module requires additional review when modified.
+ - This driver will have external input - performance data and communicate buffer in SMM mode.
+ - This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
+
+ Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmmCorePerformanceLibInternal.h"
+
+#include <Protocol/MmCommunication.h>
+#include <Protocol/SmmExitBootServices.h>
+
+SMM_BOOT_PERFORMANCE_TABLE *mSmmBootPerformanceTable = NULL;
+
+typedef struct {
+ EFI_HANDLE Handle;
+ CHAR8 NameString[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
+ EFI_GUID ModuleGuid;
+} HANDLE_GUID_MAP;
+
+HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];
+UINTN mCachePairCount = 0;
+
+UINT32 mPerformanceLength = sizeof (SMM_BOOT_PERFORMANCE_TABLE);
+UINT32 mMaxPerformanceLength = 0;
+UINT32 mLoadImageCount = 0;
+BOOLEAN mFpdtDataIsReported = FALSE;
+BOOLEAN mLackSpaceIsReport = FALSE;
+SPIN_LOCK mSmmFpdtLock;
+UINT32 mCachedLength = 0;
+UINT32 mBootRecordSize = 0;
+BOOLEAN mPerformanceMeasurementEnabled;
+
+/**
+ Return the module name and optionally module GUID for a given handle.
+
+ @param[in] Handle The image handle.
+ @param[out] NameString The buffer to store the name string.
+ @param[in] BufferSize The size of the NameString buffer in bytes.
+ @param[out] ModuleGuid An optional buffer to store the module GUID.
+
+ @retval EFI_SUCCESS The module information was successfully retrieved.
+ @retval EFI_INVALID_PARAMETER A required pointer argument is null or the given handle is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+GetModuleInfoFromHandle (
+ IN EFI_HANDLE Handle,
+ OUT CHAR8 *NameString,
+ IN UINTN BufferSize,
+ OUT EFI_GUID *ModuleGuid OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_GUID *TempGuid;
+ INTN Count;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
+
+ if ((NameString == NULL) || (BufferSize == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Try to get the ModuleGuid and name string form the cached array.
+ //
+ if (mCachePairCount > 0) {
+ for (Count = mCachePairCount - 1; Count >= 0; Count--) {
+ if (Handle == mCacheHandleGuidTable[Count].Handle) {
+ CopyGuid (ModuleGuid, &mCacheHandleGuidTable[Count].ModuleGuid);
+ AsciiStrCpyS (NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, mCacheHandleGuidTable[Count].NameString);
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ Status = EFI_INVALID_PARAMETER;
+ NameString[0] = 0;
+ TempGuid = &gZeroGuid;
+
+ LoadedImage = GetLoadedImageProtocol (Handle);
+ if (LoadedImage != NULL) {
+ //
+ // Get Module Guid from DevicePath.
+ //
+ if ((LoadedImage->FilePath != NULL) &&
+ (LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH) &&
+ (LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP)
+ )
+ {
+ //
+ // Determine GUID associated with module logging performance
+ //
+ FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath;
+ TempGuid = &FvFilePath->FvFileName;
+ }
+
+ if (GetModuleNameFromPdbString (LoadedImage->ImageBase, NameString, BufferSize) == EFI_SUCCESS) {
+ goto Done;
+ }
+ }
+
+ if (!IsZeroGuid (TempGuid)) {
+ Status = GetNameFromUiSection (TempGuid, NameString, BufferSize);
+ }
+
+Done:
+ //
+ // Copy Module Guid
+ //
+ if (ModuleGuid != NULL) {
+ CopyGuid (ModuleGuid, TempGuid);
+ if (IsZeroGuid (TempGuid) && (Handle != NULL)) {
+ // Handle is GUID
+ CopyGuid (ModuleGuid, (EFI_GUID *)Handle);
+ }
+ }
+
+ //
+ // Cache the Handle and Guid pairs.
+ //
+ if (mCachePairCount < CACHE_HANDLE_GUID_COUNT) {
+ mCacheHandleGuidTable[mCachePairCount].Handle = Handle;
+ CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, ModuleGuid);
+ AsciiStrCpyS (mCacheHandleGuidTable[mCachePairCount].NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, NameString);
+ mCachePairCount++;
+ }
+
+ return Status;
+}
+
+/**
+ Get the module name from the PDB file name in the image header.
+
+ @param[in] ImageBase The base address of the image.
+ @param[out] NameString The buffer to store the name string.
+ @param[in] BufferSize The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The name string is successfully retrieved.
+ @retval EFI_INVALID_PARAMETER A pointer argument provided is null.
+ @retval EFI_NOT_FOUND The module name was not found.
+
+**/
+EFI_STATUS
+GetModuleNameFromPdbString (
+ IN VOID *ImageBase,
+ OUT CHAR8 *NameString,
+ IN UINTN BufferSize
+ )
+{
+ CHAR8 *PdbFileName;
+ UINTN Index;
+ UINTN StartIndex;
+
+ if ((ImageBase == NULL) || (NameString == NULL) || (BufferSize == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PdbFileName = PeCoffLoaderGetPdbPointer (ImageBase);
+
+ if (PdbFileName == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (StartIndex = 0, Index = 0; PdbFileName[Index] != 0; Index++) {
+ if ((PdbFileName[Index] == '\\') || (PdbFileName[Index] == '/')) {
+ StartIndex = Index + 1;
+ }
+ }
+
+ //
+ // Copy the PDB file name to our temporary string.
+ // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
+ //
+ for (Index = 0; Index < BufferSize - 1; Index++) {
+ NameString[Index] = PdbFileName[Index + StartIndex];
+ if ((NameString[Index] == 0) || (NameString[Index] == '.')) {
+ NameString[Index] = 0;
+ break;
+ }
+ }
+
+ if (Index == BufferSize - 1) {
+ NameString[Index] = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the pointer to the FPDT record in the allocated memory.
+
+ @param RecordSize The size of FPDT record.
+ @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.
+
+ @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.
+ @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.
+**/
+EFI_STATUS
+GetFpdtRecordPtr (
+ IN UINT8 RecordSize,
+ IN OUT FPDT_RECORD_PTR *FpdtRecordPtr
+ )
+{
+ if (mFpdtDataIsReported) {
+ //
+ // Append Boot records after Smm boot performance records have been reported.
+ //
+ if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+ if (!mLackSpaceIsReport) {
+ DEBUG ((DEBUG_ERROR, "[%a] - Not enough space to save boot records\n", __func__));
+ mLackSpaceIsReport = TRUE;
+ }
+
+ return EFI_OUT_OF_RESOURCES;
+ } else {
+ //
+ // Covert buffer to FPDT Ptr Union type.
+ //
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
+ }
+ } else {
+ //
+ // Check if pre-allocated buffer is full
+ //
+ if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
+ mSmmBootPerformanceTable = ReallocatePool (
+ mPerformanceLength,
+ mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER,
+ mSmmBootPerformanceTable
+ );
+
+ if (mSmmBootPerformanceTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mSmmBootPerformanceTable->Header.Length = mPerformanceLength;
+ mMaxPerformanceLength = mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER;
+ }
+
+ //
+ // Covert buffer to FPDT Ptr Union type.
+ //
+ FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
+ }
+
+ FpdtRecordPtr->RecordHeader->Length = 0;
+ return EFI_SUCCESS;
+}
+
+/**
+Check whether the Token is a known one which is uesed by core.
+
+@param Token Pointer to a Null-terminated ASCII string
+
+@retval TRUE Is a known one used by core.
+@retval FALSE Not a known one.
+
+**/
+BOOLEAN
+IsKnownTokens (
+ IN CONST CHAR8 *Token
+ )
+{
+ if (Token == NULL) {
+ return FALSE;
+ }
+
+ if ((AsciiStrCmp (Token, SEC_TOK) == 0) ||
+ (AsciiStrCmp (Token, PEI_TOK) == 0) ||
+ (AsciiStrCmp (Token, DXE_TOK) == 0) ||
+ (AsciiStrCmp (Token, BDS_TOK) == 0) ||
+ (AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0) ||
+ (AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0) ||
+ (AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0) ||
+ (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) ||
+ (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) ||
+ (AsciiStrCmp (Token, PEIM_TOK) == 0))
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+Check whether the ID is a known one which map to the known Token.
+
+@param Identifier 32-bit identifier.
+
+@retval TRUE Is a known one used by core.
+@retval FALSE Not a known one.
+
+**/
+BOOLEAN
+IsKnownID (
+ IN UINT32 Identifier
+ )
+{
+ if ((Identifier == MODULE_START_ID) ||
+ (Identifier == MODULE_END_ID) ||
+ (Identifier == MODULE_LOADIMAGE_START_ID) ||
+ (Identifier == MODULE_LOADIMAGE_END_ID) ||
+ (Identifier == MODULE_DB_START_ID) ||
+ (Identifier == MODULE_DB_END_ID) ||
+ (Identifier == MODULE_DB_SUPPORT_START_ID) ||
+ (Identifier == MODULE_DB_SUPPORT_END_ID) ||
+ (Identifier == MODULE_DB_STOP_START_ID) ||
+ (Identifier == MODULE_DB_STOP_END_ID))
+ {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Get the FPDT record identifier.
+
+ @param Attribute The attribute of the Record.
+ PerfStartEntry: Start Record.
+ PerfEndEntry: End Record.
+ @param Handle Pointer to environment specific context used to identify the component being measured.
+ @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.
+ @param ProgressID On return, pointer to the ProgressID.
+
+ @retval EFI_SUCCESS Get record info successfully.
+ @retval EFI_INVALID_PARAMETER No matched FPDT record.
+
+**/
+EFI_STATUS
+GetFpdtRecordId (
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute,
+ IN CONST VOID *Handle,
+ IN CONST CHAR8 *String,
+ OUT UINT16 *ProgressID
+ )
+{
+ //
+ // Token to Id.
+ //
+ if (String != NULL) {
+ if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) {
+ // "StartImage:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_START_ID;
+ } else {
+ *ProgressID = MODULE_END_ID;
+ }
+ } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) {
+ // "LoadImage:"
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = MODULE_LOADIMAGE_START_ID;
+ } else {
+ *ProgressID = MODULE_LOADIMAGE_END_ID;
+ }
+ } else {
+ // Pref used in Modules
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
+ } else {
+ *ProgressID = PERF_INMODULE_END_ID;
+ }
+ }
+ } else if (Handle != NULL) {
+ // Pref used in Modules
+ if (Attribute == PerfStartEntry) {
+ *ProgressID = PERF_INMODULE_START_ID;
+ } else {
+ *ProgressID = PERF_INMODULE_END_ID;
+ }
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Copies the string from Source into Destination and updates Length with the
+ size of the string.
+
+ @param Destination - destination of the string copy
+ @param Source - pointer to the source string which will get copied
+ @param Length - pointer to a length variable to be updated
+
+**/
+VOID
+CopyStringIntoPerfRecordAndUpdateLength (
+ IN OUT CHAR8 *Destination,
+ IN CONST CHAR8 *Source,
+ IN OUT UINT8 *Length
+ )
+{
+ UINTN StringLen;
+ UINTN DestMax;
+
+ ASSERT (Source != NULL);
+
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ DestMax = STRING_SIZE;
+ } else {
+ DestMax = AsciiStrSize (Source);
+ if (DestMax > STRING_SIZE) {
+ DestMax = STRING_SIZE;
+ }
+ }
+
+ StringLen = AsciiStrLen (Source);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+
+ AsciiStrnCpyS (Destination, DestMax, Source, StringLen);
+ *Length += (UINT8)DestMax;
+
+ return;
+}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID.
+ @param Guid - Pointer to a GUID.
+ @param String - Pointer to a string describing the measurement.
+ @param Ticker - 64-bit time stamp.
+ @param Address - Pointer to a location in memory relevant to the measurement.
+ @param PerfId - Performance identifier describing the type of measurement.
+ @param Attribute - The attribute of the measurement. According to attribute can create a start
+ record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+ or a general record for other Perf macros.
+
+ @retval EFI_SUCCESS - Successfully created performance record.
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId.
+
+ @retval EFI_SUCCESS - Successfully created performance record
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+EFI_STATUS
+InsertFpdtRecord (
+ IN CONST VOID *CallerIdentifier OPTIONAL,
+ IN CONST VOID *Guid OPTIONAL,
+ IN CONST CHAR8 *String OPTIONAL,
+ IN UINT64 Ticker,
+ IN UINT64 Address OPTIONAL,
+ IN UINT16 PerfId,
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute
+ )
+
+{
+ EFI_STATUS Status;
+ EFI_GUID ModuleGuid;
+ CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
+ FPDT_RECORD_PTR FpdtRecordPtr;
+ FPDT_RECORD_PTR CachedFpdtRecordPtr;
+ UINT64 TimeStamp;
+ CONST CHAR8 *StringPtr;
+ UINTN DestMax;
+ UINTN StringLen;
+ UINT16 ProgressId;
+
+ StringPtr = NULL;
+ ZeroMem (ModuleName, sizeof (ModuleName));
+
+ //
+ // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
+ // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
+ //
+ if (Attribute != PerfEntry) {
+ //
+ // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
+ // !!! Note: If the Perf is not the known Token used in the core but have same
+ // ID with the core Token, this case will not be supported.
+ // And in currtnt usage mode, for the unkown ID, there is a general rule:
+ // If it is start pref: the lower 4 bits of the ID should be 0.
+ // If it is end pref: the lower 4 bits of the ID should not be 0.
+ // If input ID doesn't follow the rule, we will adjust it.
+ //
+ if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ return EFI_INVALID_PARAMETER;
+ } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
+ if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {
+ PerfId &= 0xFFF0;
+ } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
+ PerfId += 1;
+ }
+ }
+
+ if (PerfId == 0) {
+ //
+ // Get ProgressID form the String Token.
+ //
+ Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PerfId = ProgressId;
+ }
+ }
+
+ //
+ // 2. Get the buffer to store the FPDT record.
+ //
+ Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // 3. Get the TimeStamp.
+ //
+ if (Ticker == 0) {
+ Ticker = GetPerformanceCounter ();
+ TimeStamp = GetTimeInNanoSecond (Ticker);
+ } else if (Ticker == 1) {
+ TimeStamp = 0;
+ } else {
+ TimeStamp = GetTimeInNanoSecond (Ticker);
+ }
+
+ //
+ // 4. Fill in the FPDT record according to different Performance Identifier.
+ //
+ switch (PerfId) {
+ case MODULE_START_ID:
+ case MODULE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ //
+ // Cache the offset of start image start record and use to update the start image end record if needed.
+ //
+ if ((PerfId == MODULE_START_ID) && (Attribute == PerfEntry)) {
+ mCachedLength = mSmmBootPerformanceTable->Header.Length;
+ }
+
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
+ FpdtRecordPtr.GuidEvent->Header.Length = sizeof (FPDT_GUID_EVENT_RECORD);
+ FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ if ((CallerIdentifier == NULL) && (PerfId == MODULE_END_ID) && (mCachedLength != 0)) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mCachedLength);
+ CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
+ mCachedLength = 0;
+ }
+ }
+
+ break;
+
+ case MODULE_LOADIMAGE_START_ID:
+ case MODULE_LOADIMAGE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ StringPtr = ModuleName;
+ if (PerfId == MODULE_LOADIMAGE_START_ID) {
+ mLoadImageCount++;
+ //
+ // Cache the offset of load image start record and use to be updated by the load image end record if needed.
+ //
+ if ((CallerIdentifier == NULL) && (Attribute == PerfEntry)) {
+ mCachedLength = mSmmBootPerformanceTable->Header.Length;
+ }
+ }
+
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
+ FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
+ FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;
+ FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
+ FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;
+ CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
+ if ((PerfId == MODULE_LOADIMAGE_END_ID) && (mCachedLength != 0)) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mCachedLength);
+ CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));
+ mCachedLength = 0;
+ }
+ }
+
+ break;
+
+ case PERF_EVENTSIGNAL_START_ID:
+ case PERF_EVENTSIGNAL_END_ID:
+ case PERF_CALLBACK_START_ID:
+ case PERF_CALLBACK_END_ID:
+ if ((String == NULL) || (Guid == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ StringPtr = String;
+ if (AsciiStrLen (String) == 0) {
+ StringPtr = "unknown name";
+ }
+
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DualGuidStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DualGuidStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DualGuidStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
+ CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);
+ }
+
+ break;
+
+ case PERF_EVENT_ID:
+ case PERF_FUNCTION_START_ID:
+ case PERF_FUNCTION_END_ID:
+ case PERF_INMODULE_START_ID:
+ case PERF_INMODULE_END_ID:
+ case PERF_CROSSMODULE_START_ID:
+ case PERF_CROSSMODULE_END_ID:
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ if (String != NULL) {
+ StringPtr = String;
+ } else {
+ StringPtr = ModuleName;
+ }
+
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+ }
+
+ break;
+
+ default:
+ if (Attribute != PerfEntry) {
+ GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
+ if (String != NULL) {
+ StringPtr = String;
+ } else {
+ StringPtr = ModuleName;
+ }
+
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+
+ if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+ }
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ break;
+ }
+
+ //
+ // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
+ //
+ if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
+ if (StringPtr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
+ FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
+ FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
+ if (Guid != NULL) {
+ //
+ // Cache the event guid in string event record.
+ //
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ } else {
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
+ }
+
+ if (AsciiStrLen (StringPtr) == 0) {
+ StringPtr = "unknown name";
+ }
+
+ CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
+
+ if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {
+ FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);
+ }
+
+ if (((PerfId == MODULE_LOADIMAGE_END_ID) || (PerfId == MODULE_END_ID)) && (mCachedLength != 0)) {
+ CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mCachedLength);
+ if (PerfId == MODULE_LOADIMAGE_END_ID) {
+ DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ StringLen = AsciiStrLen (StringPtr);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+
+ CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+ AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);
+ } else if (PerfId == MODULE_END_ID) {
+ DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
+ StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);
+ if (StringLen >= DestMax) {
+ StringLen = DestMax -1;
+ }
+
+ CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
+ AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);
+ }
+
+ mCachedLength = 0;
+ }
+ }
+
+ //
+ // 5. Update the length of the used buffer after fill in the record.
+ //
+ mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;
+ mSmmBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Communication service SMI Handler entry.
+
+ This SMI handler provides services for report MM boot records.
+
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param[in] RegisterContext Points to an optional handler context which was specified when the
+ handler was registered.
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-MM environment into an MM environment.
+ @param[in, out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
+ should still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
+ still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
+ be called.
+ @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
+
+**/
+EFI_STATUS
+EFIAPI
+FpdtSmiHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *RegisterContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
+ UINTN BootRecordOffset;
+ UINTN BootRecordSize;
+ VOID *BootRecordData;
+ UINTN TempCommBufferSize;
+ UINT8 *BootRecordBuffer;
+
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {
+ return EFI_SUCCESS;
+ }
+
+ TempCommBufferSize = *CommBufferSize;
+
+ if (TempCommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) {
+ return EFI_SUCCESS;
+ }
+
+ if (!MmCorePerformanceIsPrimaryBufferValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ ASSERT (FALSE);
+ return EFI_SUCCESS;
+ }
+
+ SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE *)CommBuffer;
+
+ Status = EFI_SUCCESS;
+
+ switch (SmmCommData->Function) {
+ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE:
+ DEBUG ((DEBUG_VERBOSE, "[%a] - SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE entry.\n", __func__));
+ if (mSmmBootPerformanceTable != NULL) {
+ mBootRecordSize = mSmmBootPerformanceTable->Header.Length - sizeof (SMM_BOOT_PERFORMANCE_TABLE);
+ }
+
+ SmmCommData->BootRecordSize = mBootRecordSize;
+ break;
+
+ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA:
+ DEBUG ((DEBUG_VERBOSE, "[%a] - SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA entry.\n", __func__));
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET:
+ DEBUG ((DEBUG_VERBOSE, "[%a] - SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET entry.\n", __func__));
+ BootRecordOffset = SmmCommData->BootRecordOffset;
+ BootRecordData = SmmCommData->BootRecordData;
+ BootRecordSize = SmmCommData->BootRecordSize;
+
+ if (BootRecordOffset >= mBootRecordSize) {
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ if (BootRecordData == NULL) {
+ BootRecordData = (UINT8 *)SmmCommData + sizeof (SMM_BOOT_RECORD_COMMUNICATE);
+ } else if (!MmCorePerformanceIsNonPrimaryBufferValid ((UINTN)BootRecordData, BootRecordSize)) {
+ Status = EFI_ACCESS_DENIED;
+ break;
+ }
+
+ //
+ // Sanity check
+ //
+ if (BootRecordSize > mBootRecordSize - BootRecordOffset) {
+ BootRecordSize = mBootRecordSize - BootRecordOffset;
+ }
+
+ // Note: Comm size passed to this handler already has OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) removed.
+ if ((SmmCommData->BootRecordData == NULL) && (BootRecordSize > TempCommBufferSize - sizeof (SMM_BOOT_RECORD_COMMUNICATE))) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ SmmCommData->BootRecordSize = BootRecordSize;
+ BootRecordBuffer = ((UINT8 *)(mSmmBootPerformanceTable)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE);
+ CopyMem (
+ (UINT8 *)BootRecordData,
+ BootRecordBuffer + BootRecordOffset,
+ BootRecordSize
+ );
+ mFpdtDataIsReported = TRUE;
+ break;
+
+ default:
+ Status = EFI_UNSUPPORTED;
+ }
+
+ SmmCommData->ReturnStatus = Status;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the Event call back function is triggered in SMM to notify the Library
+ the system is entering runtime phase.
+
+ @param[in] Protocol Points to the protocol's unique identifier
+ @param[in] Interface Points to the interface instance
+ @param[in] Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
+ **/
+EFI_STATUS
+EFIAPI
+SmmCorePerformanceLibExitBootServicesCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ //
+ // Disable performance measurement after ExitBootServices because
+ // 1. Performance measurement might impact SMI latency at runtime;
+ // 2. Performance log is copied to non SMRAM at ReadyToBoot so runtime performance
+ // log is not useful.
+ //
+ mPerformanceMeasurementEnabled = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID.
+ @param Guid - Pointer to a GUID.
+ @param String - Pointer to a string describing the measurement.
+ @param TimeStamp - 64-bit time stamp.
+ @param Address - Pointer to a location in memory relevant to the measurement.
+ @param Identifier - Performance identifier describing the type of measurement.
+ @param Attribute - The attribute of the measurement. According to attribute can create a start
+ record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
+ or a general record for other Perf macros.
+
+ @retval EFI_SUCCESS - Successfully created performance record.
+ @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
+ @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId.
+**/
+EFI_STATUS
+EFIAPI
+CreatePerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier OPTIONAL,
+ IN CONST VOID *Guid OPTIONAL,
+ IN CONST CHAR8 *String OPTIONAL,
+ IN UINT64 TimeStamp OPTIONAL,
+ IN UINT64 Address OPTIONAL,
+ IN UINT32 Identifier,
+ IN PERF_MEASUREMENT_ATTRIBUTE Attribute
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ AcquireSpinLock (&mSmmFpdtLock);
+ Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);
+ ReleaseSpinLock (&mSmmFpdtLock);
+ return Status;
+}
+
+/**
+ Adds a record at the end of the performance measurement log
+ that records the start time of a performance measurement.
+
+ Adds a record to the end of the performance measurement log
+ that contains the Handle, Token, Module and Identifier.
+ The end time of the new record must be set to zero.
+ If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
+ If TimeStamp is zero, the start time in the record is filled in with the value
+ read from the current time stamp.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+ @param Identifier 32-bit identifier. If the value is 0, the created record
+ is same as the one created by StartPerformanceMeasurement.
+
+ @retval RETURN_SUCCESS The start of the measurement was recorded.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
+
+**/
+RETURN_STATUS
+EFIAPI
+StartPerformanceMeasurementEx (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp,
+ IN UINT32 Identifier
+ )
+{
+ CONST CHAR8 *String;
+
+ if (Token != NULL) {
+ String = Token;
+ } else if (Module != NULL) {
+ String = Module;
+ } else {
+ String = NULL;
+ }
+
+ return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
+}
+
+/**
+ Searches the performance measurement log from the beginning of the log
+ for the first matching record that contains a zero end time and fills in a valid end time.
+
+ Searches the performance measurement log from the beginning of the log
+ for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
+ If the record can not be found then return RETURN_NOT_FOUND.
+ If the record is found and TimeStamp is not zero,
+ then the end time in the record is filled in with the value specified by TimeStamp.
+ If the record is found and TimeStamp is zero, then the end time in the matching record
+ is filled in with the current time stamp value.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+ @param Identifier 32-bit identifier. If the value is 0, the found record
+ is same as the one found by EndPerformanceMeasurement.
+
+ @retval RETURN_SUCCESS The end of the measurement was recorded.
+ @retval RETURN_NOT_FOUND The specified measurement record could not be found.
+
+**/
+RETURN_STATUS
+EFIAPI
+EndPerformanceMeasurementEx (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp,
+ IN UINT32 Identifier
+ )
+{
+ CONST CHAR8 *String;
+
+ if (Token != NULL) {
+ String = Token;
+ } else if (Module != NULL) {
+ String = Module;
+ } else {
+ String = NULL;
+ }
+
+ return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
+}
+
+/**
+ Attempts to retrieve a performance measurement log entry from the performance measurement log.
+ It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
+ and then assign the Identifier with 0.
+
+ !!! Not Support!!!
+
+ Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
+ zero on entry, then an attempt is made to retrieve the first entry from the performance log,
+ and the key for the second entry in the log is returned. If the performance log is empty,
+ then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
+ log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
+ returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
+ retrieved and an implementation specific non-zero key value that specifies the end of the performance
+ log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
+ is retrieved and zero is returned. In the cases where a performance log entry can be returned,
+ the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
+ If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
+ If Handle is NULL, then ASSERT().
+ If Token is NULL, then ASSERT().
+ If Module is NULL, then ASSERT().
+ If StartTimeStamp is NULL, then ASSERT().
+ If EndTimeStamp is NULL, then ASSERT().
+ If Identifier is NULL, then ASSERT().
+
+ @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
+ 0, then the first performance measurement log entry is retrieved.
+ On exit, the key of the next performance log entry.
+ @param Handle Pointer to environment specific context used to identify the component
+ being measured.
+ @param Token Pointer to a Null-terminated ASCII string that identifies the component
+ being measured.
+ @param Module Pointer to a Null-terminated ASCII string that identifies the module
+ being measured.
+ @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was started.
+ @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was ended.
+ @param Identifier Pointer to the 32-bit identifier that was recorded.
+
+ @return The key for the next performance log entry (in general case).
+
+**/
+UINTN
+EFIAPI
+GetPerformanceMeasurementEx (
+ IN UINTN LogEntryKey,
+ OUT CONST VOID **Handle,
+ OUT CONST CHAR8 **Token,
+ OUT CONST CHAR8 **Module,
+ OUT UINT64 *StartTimeStamp,
+ OUT UINT64 *EndTimeStamp,
+ OUT UINT32 *Identifier
+ )
+{
+ return 0;
+}
+
+/**
+ Adds a record at the end of the performance measurement log
+ that records the start time of a performance measurement.
+
+ Adds a record to the end of the performance measurement log
+ that contains the Handle, Token, and Module.
+ The end time of the new record must be set to zero.
+ If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
+ If TimeStamp is zero, the start time in the record is filled in with the value
+ read from the current time stamp.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+
+ @retval RETURN_SUCCESS The start of the measurement was recorded.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
+
+**/
+RETURN_STATUS
+EFIAPI
+StartPerformanceMeasurement (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp
+ )
+{
+ return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
+}
+
+/**
+ Searches the performance measurement log from the beginning of the log
+ for the first matching record that contains a zero end time and fills in a valid end time.
+
+ Searches the performance measurement log from the beginning of the log
+ for the first record that matches Handle, Token, and Module and has an end time value of zero.
+ If the record can not be found then return RETURN_NOT_FOUND.
+ If the record is found and TimeStamp is not zero,
+ then the end time in the record is filled in with the value specified by TimeStamp.
+ If the record is found and TimeStamp is zero, then the end time in the matching record
+ is filled in with the current time stamp value.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+
+ @retval RETURN_SUCCESS The end of the measurement was recorded.
+ @retval RETURN_NOT_FOUND The specified measurement record could not be found.
+
+**/
+RETURN_STATUS
+EFIAPI
+EndPerformanceMeasurement (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp
+ )
+{
+ return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
+}
+
+/**
+ Attempts to retrieve a performance measurement log entry from the performance measurement log.
+ It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
+ and then eliminate the Identifier.
+
+ !!! Not Support!!!
+
+ Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
+ zero on entry, then an attempt is made to retrieve the first entry from the performance log,
+ and the key for the second entry in the log is returned. If the performance log is empty,
+ then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
+ log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
+ returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
+ retrieved and an implementation specific non-zero key value that specifies the end of the performance
+ log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
+ is retrieved and zero is returned. In the cases where a performance log entry can be returned,
+ the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
+ If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
+ If Handle is NULL, then ASSERT().
+ If Token is NULL, then ASSERT().
+ If Module is NULL, then ASSERT().
+ If StartTimeStamp is NULL, then ASSERT().
+ If EndTimeStamp is NULL, then ASSERT().
+
+ @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
+ 0, then the first performance measurement log entry is retrieved.
+ On exit, the key of the next performance log entry.
+ @param Handle Pointer to environment specific context used to identify the component
+ being measured.
+ @param Token Pointer to a Null-terminated ASCII string that identifies the component
+ being measured.
+ @param Module Pointer to a Null-terminated ASCII string that identifies the module
+ being measured.
+ @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was started.
+ @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was ended.
+
+ @return The key for the next performance log entry (in general case).
+
+**/
+UINTN
+EFIAPI
+GetPerformanceMeasurement (
+ IN UINTN LogEntryKey,
+ OUT CONST VOID **Handle,
+ OUT CONST CHAR8 **Token,
+ OUT CONST CHAR8 **Module,
+ OUT UINT64 *StartTimeStamp,
+ OUT UINT64 *EndTimeStamp
+ )
+{
+ return 0;
+}
+
+/**
+ Returns TRUE if the performance measurement macros are enabled.
+
+ This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is set.
+ @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+PerformanceMeasurementEnabled (
+ VOID
+ )
+{
+ return mPerformanceMeasurementEnabled;
+}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID
+ @param Guid - Pointer to a GUID
+ @param String - Pointer to a string describing the measurement
+ @param Address - Pointer to a location in memory relevant to the measurement
+ @param Identifier - Performance identifier describing the type of measurement
+
+ @retval RETURN_SUCCESS - Successfully created performance record
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier,
+ IN CONST VOID *Guid OPTIONAL,
+ IN CONST CHAR8 *String OPTIONAL,
+ IN UINT64 Address OPTIONAL,
+ IN UINT32 Identifier
+ )
+{
+ return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+}
+
+/**
+ Check whether the specified performance measurement can be logged.
+
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+ @param Type - Type of the performance measurement entry.
+
+ @retval TRUE The performance measurement can be logged.
+ @retval FALSE The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+ IN CONST UINTN Type
+ )
+{
+ //
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+ //
+ if (PerformanceMeasurementEnabled () && ((PcdGet8 (PcdPerformanceLibraryPropertyMask) & Type) == 0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
index 2700f5a..96bff30 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c
@@ -17,954 +17,177 @@
SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SmmCorePerformanceLibInternal.h"
-#define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
-#define FIRMWARE_RECORD_BUFFER 0x1000
-#define CACHE_HANDLE_GUID_COUNT 0x100
+#include <Library/DxeServicesLib.h>
+#include <Library/SmmMemLib.h>
+#include <Library/SmmServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/SmmBase2.h>
+#include <Protocol/SmmExitBootServices.h>
-SMM_BOOT_PERFORMANCE_TABLE *mSmmBootPerformanceTable = NULL;
-
-typedef struct {
- EFI_HANDLE Handle;
- CHAR8 NameString[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
- EFI_GUID ModuleGuid;
-} HANDLE_GUID_MAP;
-
-HANDLE_GUID_MAP mCacheHandleGuidTable[CACHE_HANDLE_GUID_COUNT];
-UINTN mCachePairCount = 0;
-
-UINT32 mPerformanceLength = sizeof (SMM_BOOT_PERFORMANCE_TABLE);
-UINT32 mMaxPerformanceLength = 0;
-UINT32 mLoadImageCount = 0;
-BOOLEAN mFpdtDataIsReported = FALSE;
-BOOLEAN mLackSpaceIsReport = FALSE;
-CHAR8 *mPlatformLanguage = NULL;
-SPIN_LOCK mSmmFpdtLock;
PERFORMANCE_PROPERTY mPerformanceProperty;
-UINT32 mCachedLength = 0;
-UINT32 mBootRecordSize = 0;
-BOOLEAN mPerformanceMeasurementEnabled;
-//
-// Interfaces for SMM PerformanceMeasurement Protocol.
-//
+extern SPIN_LOCK mSmmFpdtLock;
+
EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
CreatePerformanceMeasurement,
};
/**
- Return the pointer to the FPDT record in the allocated memory.
+ A library internal MM-instance specific implementation to check if a buffer outside MM is valid.
- @param RecordSize The size of FPDT record.
- @param FpdtRecordPtr Pointer the FPDT record in the allocated memory.
+ This function is provided so Standalone MM and Traditional MM may use a different implementation
+ of data buffer check logic.
- @retval EFI_SUCCESS Successfully get the pointer to the FPDT record.
- @retval EFI_OUT_OF_RESOURCES Ran out of space to store the records.
-**/
-EFI_STATUS
-GetFpdtRecordPtr (
- IN UINT8 RecordSize,
- IN OUT FPDT_RECORD_PTR *FpdtRecordPtr
- )
-{
- if (mFpdtDataIsReported) {
- //
- // Append Boot records after Smm boot performance records have been reported.
- //
- if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
- if (!mLackSpaceIsReport) {
- DEBUG ((DEBUG_INFO, "SmmCorePerformanceLib: No enough space to save boot records\n"));
- mLackSpaceIsReport = TRUE;
- }
-
- return EFI_OUT_OF_RESOURCES;
- } else {
- //
- // Covert buffer to FPDT Ptr Union type.
- //
- FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
- }
- } else {
- //
- // Check if pre-allocated buffer is full
- //
- if (mPerformanceLength + RecordSize > mMaxPerformanceLength) {
- mSmmBootPerformanceTable = ReallocatePool (
- mPerformanceLength,
- mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER,
- mSmmBootPerformanceTable
- );
-
- if (mSmmBootPerformanceTable == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- mSmmBootPerformanceTable->Header.Length = mPerformanceLength;
- mMaxPerformanceLength = mPerformanceLength + RecordSize + FIRMWARE_RECORD_BUFFER;
- }
-
- //
- // Covert buffer to FPDT Ptr Union type.
- //
- FpdtRecordPtr->RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mSmmBootPerformanceTable->Header.Length);
- }
-
- FpdtRecordPtr->RecordHeader->Length = 0;
- return EFI_SUCCESS;
-}
-
-/**
-Check whether the Token is a known one which is uesed by core.
-
-@param Token Pointer to a Null-terminated ASCII string
-
-@retval TRUE Is a known one used by core.
-@retval FALSE Not a known one.
+ @param[in] Buffer The buffer start address to be checked.
+ @param[in] Length The buffer length to be checked.
+ @retval TRUE This buffer is valid per processor architecture.
+ @retval FALSE This buffer is not valid per processor architecture.
**/
BOOLEAN
-IsKnownTokens (
- IN CONST CHAR8 *Token
+MmCorePerformanceIsNonPrimaryBufferValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
)
{
- if (Token == NULL) {
- return FALSE;
- }
-
- if ((AsciiStrCmp (Token, SEC_TOK) == 0) ||
- (AsciiStrCmp (Token, PEI_TOK) == 0) ||
- (AsciiStrCmp (Token, DXE_TOK) == 0) ||
- (AsciiStrCmp (Token, BDS_TOK) == 0) ||
- (AsciiStrCmp (Token, DRIVERBINDING_START_TOK) == 0) ||
- (AsciiStrCmp (Token, DRIVERBINDING_SUPPORT_TOK) == 0) ||
- (AsciiStrCmp (Token, DRIVERBINDING_STOP_TOK) == 0) ||
- (AsciiStrCmp (Token, LOAD_IMAGE_TOK) == 0) ||
- (AsciiStrCmp (Token, START_IMAGE_TOK) == 0) ||
- (AsciiStrCmp (Token, PEIM_TOK) == 0))
- {
- return TRUE;
- } else {
- return FALSE;
- }
+ return SmmIsBufferOutsideSmmValid (Buffer, Length);
}
/**
-Check whether the ID is a known one which map to the known Token.
+ A library internal MM-instance specific implementation to check if a comm buffer is valid.
-@param Identifier 32-bit identifier.
+ This function is provided so Standalone MM and Traditional MM may use a different implementation
+ of comm buffer check logic.
-@retval TRUE Is a known one used by core.
-@retval FALSE Not a known one.
+ @param[in] Buffer The buffer start address to be checked.
+ @param[in] Length The buffer length to be checked.
+ @retval TRUE This communicate buffer is valid per processor architecture.
+ @retval FALSE This communicate buffer is not valid per processor architecture.
**/
BOOLEAN
-IsKnownID (
- IN UINT32 Identifier
- )
-{
- if ((Identifier == MODULE_START_ID) ||
- (Identifier == MODULE_END_ID) ||
- (Identifier == MODULE_LOADIMAGE_START_ID) ||
- (Identifier == MODULE_LOADIMAGE_END_ID) ||
- (Identifier == MODULE_DB_START_ID) ||
- (Identifier == MODULE_DB_END_ID) ||
- (Identifier == MODULE_DB_SUPPORT_START_ID) ||
- (Identifier == MODULE_DB_SUPPORT_END_ID) ||
- (Identifier == MODULE_DB_STOP_START_ID) ||
- (Identifier == MODULE_DB_STOP_END_ID))
- {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-/**
- Get the FPDT record identifier.
-
- @param Attribute The attribute of the Record.
- PerfStartEntry: Start Record.
- PerfEndEntry: End Record.
- @param Handle Pointer to environment specific context used to identify the component being measured.
- @param String Pointer to a Null-terminated ASCII string that identifies the component being measured.
- @param ProgressID On return, pointer to the ProgressID.
-
- @retval EFI_SUCCESS Get record info successfully.
- @retval EFI_INVALID_PARAMETER No matched FPDT record.
-
-**/
-EFI_STATUS
-GetFpdtRecordId (
- IN PERF_MEASUREMENT_ATTRIBUTE Attribute,
- IN CONST VOID *Handle,
- IN CONST CHAR8 *String,
- OUT UINT16 *ProgressID
+MmCorePerformanceIsPrimaryBufferValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
)
{
- //
- // Token to Id.
- //
- if (String != NULL) {
- if (AsciiStrCmp (String, START_IMAGE_TOK) == 0) {
- // "StartImage:"
- if (Attribute == PerfStartEntry) {
- *ProgressID = MODULE_START_ID;
- } else {
- *ProgressID = MODULE_END_ID;
- }
- } else if (AsciiStrCmp (String, LOAD_IMAGE_TOK) == 0) {
- // "LoadImage:"
- if (Attribute == PerfStartEntry) {
- *ProgressID = MODULE_LOADIMAGE_START_ID;
- } else {
- *ProgressID = MODULE_LOADIMAGE_END_ID;
- }
- } else {
- // Pref used in Modules
- if (Attribute == PerfStartEntry) {
- *ProgressID = PERF_INMODULE_START_ID;
- } else {
- *ProgressID = PERF_INMODULE_END_ID;
- }
- }
- } else if (Handle != NULL) {
- // Pref used in Modules
- if (Attribute == PerfStartEntry) {
- *ProgressID = PERF_INMODULE_START_ID;
- } else {
- *ProgressID = PERF_INMODULE_END_ID;
- }
- } else {
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
+ return SmmIsBufferOutsideSmmValid (Buffer, Length);
}
/**
- Get a human readable module name and module guid for the given image handle.
- If module name can't be found, "" string will return.
- If module guid can't be found, Zero Guid will return.
+ Return a pointer to the loaded image protocol for the given handle.
- @param Handle Image handle or Controller handle.
- @param NameString The ascii string will be filled into it. If not found, null string will return.
- @param BufferSize Size of the input NameString buffer.
- @param ModuleGuid Point to the guid buffer to store the got module guid value.
+ @param[in] Handle A handle to query for the loaded image protocol.
- @retval EFI_SUCCESS Successfully get module name and guid.
- @retval EFI_INVALID_PARAMETER The input parameter NameString is NULL.
- @retval other value Module Name can't be got.
+ @return A pointer to a loaded image protocol instance or null if the handle does not support load image protocol.
**/
-EFI_STATUS
-EFIAPI
-GetModuleInfoFromHandle (
- IN EFI_HANDLE Handle,
- OUT CHAR8 *NameString,
- IN UINTN BufferSize,
- OUT EFI_GUID *ModuleGuid OPTIONAL
+EFI_LOADED_IMAGE_PROTOCOL *
+GetLoadedImageProtocol (
+ IN EFI_HANDLE Handle
)
{
- EFI_STATUS Status;
- EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
- CHAR8 *PdbFileName;
- EFI_GUID *TempGuid;
- UINTN StartIndex;
- UINTN Index;
- INTN Count;
- BOOLEAN ModuleGuidIsGet;
- UINTN StringSize;
- CHAR16 *StringPtr;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;
+ EFI_STATUS Status;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
- if ((NameString == NULL) || (BufferSize == 0)) {
- return EFI_INVALID_PARAMETER;
+ if (Handle == NULL) {
+ return NULL;
}
- //
- // Try to get the ModuleGuid and name string form the caached array.
- //
- if (mCachePairCount > 0) {
- for (Count = mCachePairCount - 1; Count >= 0; Count--) {
- if (Handle == mCacheHandleGuidTable[Count].Handle) {
- CopyGuid (ModuleGuid, &mCacheHandleGuidTable[Count].ModuleGuid);
- AsciiStrCpyS (NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, mCacheHandleGuidTable[Count].NameString);
- return EFI_SUCCESS;
- }
- }
- }
-
- Status = EFI_INVALID_PARAMETER;
- LoadedImage = NULL;
- ModuleGuidIsGet = FALSE;
+ LoadedImage = NULL;
//
- // Initialize GUID as zero value.
+ // Try Handle as ImageHandle.
//
- TempGuid = &gZeroGuid;
- //
- // Initialize it as "" string.
- //
- NameString[0] = 0;
-
- if (Handle != NULL) {
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ if (EFI_ERROR (Status)) {
//
- // Try Handle as ImageHandle.
+ // Try Handle as Controller Handle
//
- Status = gBS->HandleProtocol (
+ Status = gBS->OpenProtocol (
Handle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **)&LoadedImage
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **)&DriverBinding,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
-
- if (EFI_ERROR (Status)) {
- //
- // Try Handle as Controller Handle
- //
- Status = gBS->OpenProtocol (
- Handle,
- &gEfiDriverBindingProtocolGuid,
- (VOID **)&DriverBinding,
- NULL,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- //
- // Get Image protocol from ImageHandle
- //
- Status = gBS->HandleProtocol (
- DriverBinding->ImageHandle,
- &gEfiLoadedImageProtocolGuid,
- (VOID **)&LoadedImage
- );
- }
- }
- }
-
- if (!EFI_ERROR (Status) && (LoadedImage != NULL)) {
- //
- // Get Module Guid from DevicePath.
- //
- if ((LoadedImage->FilePath != NULL) &&
- (LoadedImage->FilePath->Type == MEDIA_DEVICE_PATH) &&
- (LoadedImage->FilePath->SubType == MEDIA_PIWG_FW_FILE_DP)
- )
- {
- //
- // Determine GUID associated with module logging performance
- //
- ModuleGuidIsGet = TRUE;
- FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)LoadedImage->FilePath;
- TempGuid = &FvFilePath->FvFileName;
- }
-
- //
- // Method 1 Get Module Name from PDB string.
- //
- PdbFileName = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
- if ((PdbFileName != NULL) && (BufferSize > 0)) {
- StartIndex = 0;
- for (Index = 0; PdbFileName[Index] != 0; Index++) {
- if ((PdbFileName[Index] == '\\') || (PdbFileName[Index] == '/')) {
- StartIndex = Index + 1;
- }
- }
-
- //
- // Copy the PDB file name to our temporary string.
- // If the length is bigger than BufferSize, trim the redudant characters to avoid overflow in array boundary.
- //
- for (Index = 0; Index < BufferSize - 1; Index++) {
- NameString[Index] = PdbFileName[Index + StartIndex];
- if ((NameString[Index] == 0) || (NameString[Index] == '.')) {
- NameString[Index] = 0;
- break;
- }
- }
-
- if (Index == BufferSize - 1) {
- NameString[Index] = 0;
- }
-
- //
- // Module Name is got.
- //
- goto Done;
- }
- }
-
- if (ModuleGuidIsGet) {
- //
- // Method 2 Try to get the image's FFS UI section by image GUID
- //
- StringPtr = NULL;
- StringSize = 0;
- Status = GetSectionFromAnyFv (
- TempGuid,
- EFI_SECTION_USER_INTERFACE,
- 0,
- (VOID **)&StringPtr,
- &StringSize
- );
-
if (!EFI_ERROR (Status)) {
//
- // Method 3. Get the name string from FFS UI section
+ // Get Image protocol from ImageHandle
//
- for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {
- NameString[Index] = (CHAR8)StringPtr[Index];
- }
-
- NameString[Index] = 0;
- FreePool (StringPtr);
- }
- }
-
-Done:
- //
- // Copy Module Guid
- //
- if (ModuleGuid != NULL) {
- CopyGuid (ModuleGuid, TempGuid);
- if (IsZeroGuid (TempGuid) && (Handle != NULL) && !ModuleGuidIsGet) {
- // Handle is GUID
- CopyGuid (ModuleGuid, (EFI_GUID *)Handle);
- }
- }
-
- //
- // Cache the Handle and Guid pairs.
- //
- if (mCachePairCount < CACHE_HANDLE_GUID_COUNT) {
- mCacheHandleGuidTable[mCachePairCount].Handle = Handle;
- CopyGuid (&mCacheHandleGuidTable[mCachePairCount].ModuleGuid, ModuleGuid);
- AsciiStrCpyS (mCacheHandleGuidTable[mCachePairCount].NameString, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, NameString);
- mCachePairCount++;
- }
-
- return Status;
-}
-
-/**
- Copies the string from Source into Destination and updates Length with the
- size of the string.
-
- @param Destination - destination of the string copy
- @param Source - pointer to the source string which will get copied
- @param Length - pointer to a length variable to be updated
-
-**/
-VOID
-CopyStringIntoPerfRecordAndUpdateLength (
- IN OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source,
- IN OUT UINT8 *Length
- )
-{
- UINTN StringLen;
- UINTN DestMax;
-
- ASSERT (Source != NULL);
-
- if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- DestMax = STRING_SIZE;
- } else {
- DestMax = AsciiStrSize (Source);
- if (DestMax > STRING_SIZE) {
- DestMax = STRING_SIZE;
+ Status = gBS->HandleProtocol (
+ DriverBinding->ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
}
}
- StringLen = AsciiStrLen (Source);
- if (StringLen >= DestMax) {
- StringLen = DestMax -1;
- }
-
- AsciiStrnCpyS (Destination, DestMax, Source, StringLen);
- *Length += (UINT8)DestMax;
-
- return;
+ return LoadedImage;
}
/**
- Create performance record with event description and a timestamp.
-
- @param CallerIdentifier - Image handle or pointer to caller ID GUID.
- @param Guid - Pointer to a GUID.
- @param String - Pointer to a string describing the measurement.
- @param Ticker - 64-bit time stamp.
- @param Address - Pointer to a location in memory relevant to the measurement.
- @param PerfId - Performance identifier describing the type of measurement.
- @param Attribute - The attribute of the measurement. According to attribute can create a start
- record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
- or a general record for other Perf macros.
+ Get the module name from the user interface section.
- @retval EFI_SUCCESS - Successfully created performance record.
- @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
- @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
- pointer or invalid PerfId.
+ @param[in] ModuleGuid The GUID of the module.
+ @param[out] NameString The buffer to store the name string.
+ @param[in] BufferSize The size of the buffer in bytes.
- @retval EFI_SUCCESS - Successfully created performance record
- @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records
- @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
- pointer or invalid PerfId
+ @retval EFI_SUCCESS The name string is successfully retrieved.
+ @retval EFI_NOT_FOUND The module name was not found.
**/
EFI_STATUS
-InsertFpdtRecord (
- IN CONST VOID *CallerIdentifier OPTIONAL,
- IN CONST VOID *Guid OPTIONAL,
- IN CONST CHAR8 *String OPTIONAL,
- IN UINT64 Ticker,
- IN UINT64 Address OPTIONAL,
- IN UINT16 PerfId,
- IN PERF_MEASUREMENT_ATTRIBUTE Attribute
+GetNameFromUiSection (
+ IN EFI_GUID *ModuleGuid,
+ OUT CHAR8 *NameString,
+ IN UINTN BufferSize
)
-
{
- EFI_STATUS Status;
- EFI_GUID ModuleGuid;
- CHAR8 ModuleName[FPDT_STRING_EVENT_RECORD_NAME_LENGTH];
- FPDT_RECORD_PTR FpdtRecordPtr;
- FPDT_RECORD_PTR CachedFpdtRecordPtr;
- UINT64 TimeStamp;
- CONST CHAR8 *StringPtr;
- UINTN DestMax;
- UINTN StringLen;
- UINT16 ProgressId;
-
- StringPtr = NULL;
- ZeroMem (ModuleName, sizeof (ModuleName));
-
- //
- // 1. Get the Perf Id for records from PERF_START/PERF_END, PERF_START_EX/PERF_END_EX.
- // notes: For other Perf macros (Attribute == PerfEntry), their Id is known.
- //
- if (Attribute != PerfEntry) {
- //
- // If PERF_START_EX()/PERF_END_EX() have specified the ProgressID,it has high priority.
- // !!! Note: If the Perf is not the known Token used in the core but have same
- // ID with the core Token, this case will not be supported.
- // And in currtnt usage mode, for the unkown ID, there is a general rule:
- // If it is start pref: the lower 4 bits of the ID should be 0.
- // If it is end pref: the lower 4 bits of the ID should not be 0.
- // If input ID doesn't follow the rule, we will adjust it.
- //
- if ((PerfId != 0) && (IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
- return EFI_INVALID_PARAMETER;
- } else if ((PerfId != 0) && (!IsKnownID (PerfId)) && (!IsKnownTokens (String))) {
- if ((Attribute == PerfStartEntry) && ((PerfId & 0x000F) != 0)) {
- PerfId &= 0xFFF0;
- } else if ((Attribute == PerfEndEntry) && ((PerfId & 0x000F) == 0)) {
- PerfId += 1;
- }
- }
-
- if (PerfId == 0) {
- //
- // Get ProgressID form the String Token.
- //
- Status = GetFpdtRecordId (Attribute, CallerIdentifier, String, &ProgressId);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- PerfId = ProgressId;
- }
- }
-
- //
- // 2. Get the buffer to store the FPDT record.
- //
- Status = GetFpdtRecordPtr (FPDT_MAX_PERF_RECORD_SIZE, &FpdtRecordPtr);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // 3. Get the TimeStamp.
- //
- if (Ticker == 0) {
- Ticker = GetPerformanceCounter ();
- TimeStamp = GetTimeInNanoSecond (Ticker);
- } else if (Ticker == 1) {
- TimeStamp = 0;
- } else {
- TimeStamp = GetTimeInNanoSecond (Ticker);
- }
-
- //
- // 4. Fill in the FPDT record according to different Performance Identifier.
- //
- switch (PerfId) {
- case MODULE_START_ID:
- case MODULE_END_ID:
- GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
- StringPtr = ModuleName;
- //
- // Cache the offset of start image start record and use to update the start image end record if needed.
- //
- if ((PerfId == MODULE_START_ID) && (Attribute == PerfEntry)) {
- mCachedLength = mSmmBootPerformanceTable->Header.Length;
- }
-
- if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- FpdtRecordPtr.GuidEvent->Header.Type = FPDT_GUID_EVENT_TYPE;
- FpdtRecordPtr.GuidEvent->Header.Length = sizeof (FPDT_GUID_EVENT_RECORD);
- FpdtRecordPtr.GuidEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidEvent->ProgressID = PerfId;
- FpdtRecordPtr.GuidEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
- if ((CallerIdentifier == NULL) && (PerfId == MODULE_END_ID) && (mCachedLength != 0)) {
- CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mCachedLength);
- CopyMem (&FpdtRecordPtr.GuidEvent->Guid, &CachedFpdtRecordPtr.GuidEvent->Guid, sizeof (FpdtRecordPtr.GuidEvent->Guid));
- mCachedLength = 0;
- }
- }
-
- break;
-
- case MODULE_LOADIMAGE_START_ID:
- case MODULE_LOADIMAGE_END_ID:
- GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
- StringPtr = ModuleName;
- if (PerfId == MODULE_LOADIMAGE_START_ID) {
- mLoadImageCount++;
- //
- // Cache the offset of load image start record and use to be updated by the load image end record if needed.
- //
- if ((CallerIdentifier == NULL) && (Attribute == PerfEntry)) {
- mCachedLength = mSmmBootPerformanceTable->Header.Length;
- }
- }
-
- if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- FpdtRecordPtr.GuidQwordEvent->Header.Type = FPDT_GUID_QWORD_EVENT_TYPE;
- FpdtRecordPtr.GuidQwordEvent->Header.Length = sizeof (FPDT_GUID_QWORD_EVENT_RECORD);
- FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.GuidQwordEvent->ProgressID = PerfId;
- FpdtRecordPtr.GuidQwordEvent->Timestamp = TimeStamp;
- FpdtRecordPtr.GuidQwordEvent->Qword = mLoadImageCount;
- CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.GuidQwordEvent->Guid));
- if ((PerfId == MODULE_LOADIMAGE_END_ID) && (mCachedLength != 0)) {
- CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mCachedLength);
- CopyMem (&CachedFpdtRecordPtr.GuidQwordEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.GuidQwordEvent->Guid));
- mCachedLength = 0;
- }
- }
-
- break;
-
- case PERF_EVENTSIGNAL_START_ID:
- case PERF_EVENTSIGNAL_END_ID:
- case PERF_CALLBACK_START_ID:
- case PERF_CALLBACK_END_ID:
- if ((String == NULL) || (Guid == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- StringPtr = String;
- if (AsciiStrLen (String) == 0) {
- StringPtr = "unknown name";
- }
-
- if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- FpdtRecordPtr.DualGuidStringEvent->Header.Type = FPDT_DUAL_GUID_STRING_EVENT_TYPE;
- FpdtRecordPtr.DualGuidStringEvent->Header.Length = sizeof (FPDT_DUAL_GUID_STRING_EVENT_RECORD);
- FpdtRecordPtr.DualGuidStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.DualGuidStringEvent->ProgressID = PerfId;
- FpdtRecordPtr.DualGuidStringEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid1, CallerIdentifier, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid1));
- CopyMem (&FpdtRecordPtr.DualGuidStringEvent->Guid2, Guid, sizeof (FpdtRecordPtr.DualGuidStringEvent->Guid2));
- CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DualGuidStringEvent->String, StringPtr, &FpdtRecordPtr.DualGuidStringEvent->Header.Length);
- }
-
- break;
-
- case PERF_EVENT_ID:
- case PERF_FUNCTION_START_ID:
- case PERF_FUNCTION_END_ID:
- case PERF_INMODULE_START_ID:
- case PERF_INMODULE_END_ID:
- case PERF_CROSSMODULE_START_ID:
- case PERF_CROSSMODULE_END_ID:
- GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
- if (String != NULL) {
- StringPtr = String;
- } else {
- StringPtr = ModuleName;
- }
-
- if (AsciiStrLen (StringPtr) == 0) {
- StringPtr = "unknown name";
- }
-
- if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
- FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
- FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
- CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
- }
-
- break;
-
- default:
- if (Attribute != PerfEntry) {
- GetModuleInfoFromHandle ((EFI_HANDLE)CallerIdentifier, ModuleName, sizeof (ModuleName), &ModuleGuid);
- if (String != NULL) {
- StringPtr = String;
- } else {
- StringPtr = ModuleName;
- }
-
- if (AsciiStrLen (StringPtr) == 0) {
- StringPtr = "unknown name";
- }
-
- if (!PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
- FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
- FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
- CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
- }
- } else {
- return EFI_INVALID_PARAMETER;
- }
-
- break;
- }
-
- //
- // 4.2 When PcdEdkiiFpdtStringRecordEnableOnly==TRUE, create string record for all Perf entries.
- //
- if (PcdGetBool (PcdEdkiiFpdtStringRecordEnableOnly)) {
- if (StringPtr == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- FpdtRecordPtr.DynamicStringEvent->Header.Type = FPDT_DYNAMIC_STRING_EVENT_TYPE;
- FpdtRecordPtr.DynamicStringEvent->Header.Length = sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
- FpdtRecordPtr.DynamicStringEvent->Header.Revision = FPDT_RECORD_REVISION_1;
- FpdtRecordPtr.DynamicStringEvent->ProgressID = PerfId;
- FpdtRecordPtr.DynamicStringEvent->Timestamp = TimeStamp;
- if (Guid != NULL) {
- //
- // Cache the event guid in string event record.
- //
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, Guid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
- } else {
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (FpdtRecordPtr.DynamicStringEvent->Guid));
- }
-
- if (AsciiStrLen (StringPtr) == 0) {
- StringPtr = "unknown name";
- }
-
- CopyStringIntoPerfRecordAndUpdateLength (FpdtRecordPtr.DynamicStringEvent->String, StringPtr, &FpdtRecordPtr.DynamicStringEvent->Header.Length);
-
- if ((PerfId == MODULE_LOADIMAGE_START_ID) || (PerfId == MODULE_END_ID)) {
- FpdtRecordPtr.DynamicStringEvent->Header.Length = (UINT8)(sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)+ STRING_SIZE);
+ EFI_STATUS Status;
+ CHAR16 *StringPtr;
+ UINTN Index;
+ UINTN StringSize;
+
+ StringPtr = NULL;
+ StringSize = 0;
+ Status = GetSectionFromAnyFv (
+ ModuleGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ (VOID **)&StringPtr,
+ &StringSize
+ );
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < BufferSize - 1 && StringPtr[Index] != 0; Index++) {
+ NameString[Index] = (CHAR8)StringPtr[Index];
}
- if (((PerfId == MODULE_LOADIMAGE_END_ID) || (PerfId == MODULE_END_ID)) && (mCachedLength != 0)) {
- CachedFpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)((UINT8 *)mSmmBootPerformanceTable + mCachedLength);
- if (PerfId == MODULE_LOADIMAGE_END_ID) {
- DestMax = CachedFpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
- StringLen = AsciiStrLen (StringPtr);
- if (StringLen >= DestMax) {
- StringLen = DestMax -1;
- }
-
- CopyMem (&CachedFpdtRecordPtr.DynamicStringEvent->Guid, &ModuleGuid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
- AsciiStrnCpyS (CachedFpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StringLen);
- } else if (PerfId == MODULE_END_ID) {
- DestMax = FpdtRecordPtr.DynamicStringEvent->Header.Length - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD);
- StringLen = AsciiStrLen (CachedFpdtRecordPtr.DynamicStringEvent->String);
- if (StringLen >= DestMax) {
- StringLen = DestMax -1;
- }
-
- CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, &CachedFpdtRecordPtr.DynamicStringEvent->Guid, sizeof (CachedFpdtRecordPtr.DynamicStringEvent->Guid));
- AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, CachedFpdtRecordPtr.DynamicStringEvent->String, StringLen);
- }
-
- mCachedLength = 0;
- }
+ NameString[Index] = 0;
+ FreePool (StringPtr);
}
- //
- // 5. Update the length of the used buffer after fill in the record.
- //
- mPerformanceLength += FpdtRecordPtr.RecordHeader->Length;
- mSmmBootPerformanceTable->Header.Length += FpdtRecordPtr.RecordHeader->Length;
-
- return EFI_SUCCESS;
-}
-
-/**
- Communication service SMI Handler entry.
-
- This SMI handler provides services for report MM boot records.
-
- Caution: This function may receive untrusted input.
- Communicate buffer and buffer size are external input, so this function will do basic validation.
-
- @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
- @param[in] RegisterContext Points to an optional handler context which was specified when the
- handler was registered.
- @param[in, out] CommBuffer A pointer to a collection of data in memory that will
- be conveyed from a non-MM environment into an MM environment.
- @param[in, out] CommBufferSize The size of the CommBuffer.
-
- @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
- should still be called.
- @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
- still be called.
- @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
- be called.
- @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
-
-**/
-EFI_STATUS
-EFIAPI
-FpdtSmiHandler (
- IN EFI_HANDLE DispatchHandle,
- IN CONST VOID *RegisterContext,
- IN OUT VOID *CommBuffer,
- IN OUT UINTN *CommBufferSize
- )
-{
- EFI_STATUS Status;
- SMM_BOOT_RECORD_COMMUNICATE *SmmCommData;
- UINTN BootRecordOffset;
- UINTN BootRecordSize;
- VOID *BootRecordData;
- UINTN TempCommBufferSize;
- UINT8 *BootRecordBuffer;
-
- //
- // If input is invalid, stop processing this SMI
- //
- if ((CommBuffer == NULL) || (CommBufferSize == NULL)) {
- return EFI_SUCCESS;
- }
-
- TempCommBufferSize = *CommBufferSize;
-
- if (TempCommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) {
- return EFI_SUCCESS;
- }
-
- if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
- DEBUG ((DEBUG_ERROR, "FpdtSmiHandler: MM communication data buffer in MMRAM or overflow!\n"));
- return EFI_SUCCESS;
- }
-
- SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE *)CommBuffer;
-
- Status = EFI_SUCCESS;
-
- switch (SmmCommData->Function) {
- case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE:
- if (mSmmBootPerformanceTable != NULL) {
- mBootRecordSize = mSmmBootPerformanceTable->Header.Length - sizeof (SMM_BOOT_PERFORMANCE_TABLE);
- }
-
- SmmCommData->BootRecordSize = mBootRecordSize;
- break;
-
- case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA:
- Status = EFI_UNSUPPORTED;
- break;
-
- case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET:
- BootRecordOffset = SmmCommData->BootRecordOffset;
- BootRecordData = SmmCommData->BootRecordData;
- BootRecordSize = SmmCommData->BootRecordSize;
- if ((BootRecordData == NULL) || (BootRecordOffset >= mBootRecordSize)) {
- Status = EFI_INVALID_PARAMETER;
- break;
- }
-
- //
- // Sanity check
- //
- if (BootRecordSize > mBootRecordSize - BootRecordOffset) {
- BootRecordSize = mBootRecordSize - BootRecordOffset;
- }
-
- SmmCommData->BootRecordSize = BootRecordSize;
- if (!SmmIsBufferOutsideSmmValid ((UINTN)BootRecordData, BootRecordSize)) {
- DEBUG ((DEBUG_ERROR, "FpdtSmiHandler: MM Data buffer in MMRAM or overflow!\n"));
- Status = EFI_ACCESS_DENIED;
- break;
- }
-
- BootRecordBuffer = ((UINT8 *)(mSmmBootPerformanceTable)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE);
- CopyMem (
- (UINT8 *)BootRecordData,
- BootRecordBuffer + BootRecordOffset,
- BootRecordSize
- );
- mFpdtDataIsReported = TRUE;
- break;
-
- default:
- Status = EFI_UNSUPPORTED;
- }
-
- SmmCommData->ReturnStatus = Status;
-
- return EFI_SUCCESS;
-}
-
-/**
- This is the Event call back function is triggered in SMM to notify the Library
- the system is entering runtime phase.
-
- @param[in] Protocol Points to the protocol's unique identifier
- @param[in] Interface Points to the interface instance
- @param[in] Handle The handle on which the interface was installed
-
- @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
- **/
-EFI_STATUS
-EFIAPI
-SmmCorePerformanceLibExitBootServicesCallback (
- IN CONST EFI_GUID *Protocol,
- IN VOID *Interface,
- IN EFI_HANDLE Handle
- )
-{
- //
- // Disable performance measurement after ExitBootServices because
- // 1. Performance measurement might impact SMI latency at runtime;
- // 2. Performance log is copied to non SMRAM at ReadyToBoot so runtime performance
- // log is not useful.
- //
- mPerformanceMeasurementEnabled = FALSE;
-
- return EFI_SUCCESS;
+ return Status;
}
/**
- SmmBase2 protocol notify callback function, when SMST and SMM memory service get initialized
- this function is callbacked to initialize the Smm Performance Lib
+ Initializes the MM Core Performance library after MM services are available.
- @param Event The event of notify protocol.
- @param Context Notify event context.
+ @param[in] Event The event of notify protocol.
+ @param[in] Context Notify event context.
**/
VOID
@@ -974,10 +197,10 @@ InitializeSmmCorePerformanceLib (
IN VOID *Context
)
{
- EFI_HANDLE Handle;
- EFI_HANDLE SmiHandle;
EFI_STATUS Status;
PERFORMANCE_PROPERTY *PerformanceProperty;
+ EFI_HANDLE Handle;
+ EFI_HANDLE MmiHandle;
VOID *Registration;
//
@@ -986,7 +209,7 @@ InitializeSmmCorePerformanceLib (
InitializeSpinLock (&mSmmFpdtLock);
//
- // Install the protocol interfaces for SMM performance library instance.
+ // Install the protocol interfaces for MM performance library instance.
//
Handle = NULL;
Status = gSmst->SmmInstallProtocolInterface (
@@ -998,12 +221,21 @@ InitializeSmmCorePerformanceLib (
ASSERT_EFI_ERROR (Status);
//
- // Register SMI handler.
+ // Register MMI handler.
//
- SmiHandle = NULL;
- Status = gSmst->SmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &SmiHandle);
+ MmiHandle = NULL;
+ Status = gSmst->SmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &MmiHandle);
ASSERT_EFI_ERROR (Status);
+ //
+ // Register callback function for ExitBootServices event.
+ //
+ Status = gSmst->SmmRegisterProtocolNotify (
+ &gEdkiiSmmExitBootServicesProtocolGuid,
+ SmmCorePerformanceLibExitBootServicesCallback,
+ &Registration
+ );
+
Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **)&PerformanceProperty);
if (EFI_ERROR (Status)) {
//
@@ -1018,16 +250,6 @@ InitializeSmmCorePerformanceLib (
Status = gBS->InstallConfigurationTable (&gPerformanceProtocolGuid, &mPerformanceProperty);
ASSERT_EFI_ERROR (Status);
}
-
- //
- // Register callback function for ExitBootServices event.
- //
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEdkiiSmmExitBootServicesProtocolGuid,
- SmmCorePerformanceLibExitBootServicesCallback,
- &Registration
- );
- ASSERT_EFI_ERROR (Status);
}
/**
@@ -1055,6 +277,7 @@ SmmCorePerformanceLibConstructor (
mPerformanceMeasurementEnabled = (BOOLEAN)((PcdGet8 (PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
if (!PerformanceMeasurementEnabled ()) {
+ DEBUG ((DEBUG_WARN, "[%a] - Performance library is linked but performance tracing is not enabled.\n", __func__));
//
// Do not initialize performance infrastructure if not required.
//
@@ -1086,401 +309,3 @@ SmmCorePerformanceLibConstructor (
return EFI_SUCCESS;
}
-
-/**
- Create performance record with event description and a timestamp.
-
- @param CallerIdentifier - Image handle or pointer to caller ID GUID.
- @param Guid - Pointer to a GUID.
- @param String - Pointer to a string describing the measurement.
- @param TimeStamp - 64-bit time stamp.
- @param Address - Pointer to a location in memory relevant to the measurement.
- @param Identifier - Performance identifier describing the type of measurement.
- @param Attribute - The attribute of the measurement. According to attribute can create a start
- record for PERF_START/PERF_START_EX, or a end record for PERF_END/PERF_END_EX,
- or a general record for other Perf macros.
-
- @retval EFI_SUCCESS - Successfully created performance record.
- @retval EFI_OUT_OF_RESOURCES - Ran out of space to store the records.
- @retval EFI_INVALID_PARAMETER - Invalid parameter passed to function - NULL
- pointer or invalid PerfId.
-**/
-EFI_STATUS
-EFIAPI
-CreatePerformanceMeasurement (
- IN CONST VOID *CallerIdentifier OPTIONAL,
- IN CONST VOID *Guid OPTIONAL,
- IN CONST CHAR8 *String OPTIONAL,
- IN UINT64 TimeStamp OPTIONAL,
- IN UINT64 Address OPTIONAL,
- IN UINT32 Identifier,
- IN PERF_MEASUREMENT_ATTRIBUTE Attribute
- )
-{
- EFI_STATUS Status;
-
- Status = EFI_SUCCESS;
-
- AcquireSpinLock (&mSmmFpdtLock);
- Status = InsertFpdtRecord (CallerIdentifier, Guid, String, TimeStamp, Address, (UINT16)Identifier, Attribute);
- ReleaseSpinLock (&mSmmFpdtLock);
- return Status;
-}
-
-/**
- Adds a record at the end of the performance measurement log
- that records the start time of a performance measurement.
-
- Adds a record to the end of the performance measurement log
- that contains the Handle, Token, Module and Identifier.
- The end time of the new record must be set to zero.
- If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
- If TimeStamp is zero, the start time in the record is filled in with the value
- read from the current time stamp.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
- @param Identifier 32-bit identifier. If the value is 0, the created record
- is same as the one created by StartPerformanceMeasurement.
-
- @retval RETURN_SUCCESS The start of the measurement was recorded.
- @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
-
-**/
-RETURN_STATUS
-EFIAPI
-StartPerformanceMeasurementEx (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp,
- IN UINT32 Identifier
- )
-{
- CONST CHAR8 *String;
-
- if (Token != NULL) {
- String = Token;
- } else if (Module != NULL) {
- String = Module;
- } else {
- String = NULL;
- }
-
- return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
-}
-
-/**
- Searches the performance measurement log from the beginning of the log
- for the first matching record that contains a zero end time and fills in a valid end time.
-
- Searches the performance measurement log from the beginning of the log
- for the first record that matches Handle, Token, Module and Identifier and has an end time value of zero.
- If the record can not be found then return RETURN_NOT_FOUND.
- If the record is found and TimeStamp is not zero,
- then the end time in the record is filled in with the value specified by TimeStamp.
- If the record is found and TimeStamp is zero, then the end time in the matching record
- is filled in with the current time stamp value.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
- @param Identifier 32-bit identifier. If the value is 0, the found record
- is same as the one found by EndPerformanceMeasurement.
-
- @retval RETURN_SUCCESS The end of the measurement was recorded.
- @retval RETURN_NOT_FOUND The specified measurement record could not be found.
-
-**/
-RETURN_STATUS
-EFIAPI
-EndPerformanceMeasurementEx (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp,
- IN UINT32 Identifier
- )
-{
- CONST CHAR8 *String;
-
- if (Token != NULL) {
- String = Token;
- } else if (Module != NULL) {
- String = Module;
- } else {
- String = NULL;
- }
-
- return (RETURN_STATUS)CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
-}
-
-/**
- Attempts to retrieve a performance measurement log entry from the performance measurement log.
- It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
- and then assign the Identifier with 0.
-
- !!! Not Support!!!
-
- Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
- zero on entry, then an attempt is made to retrieve the first entry from the performance log,
- and the key for the second entry in the log is returned. If the performance log is empty,
- then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
- log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
- returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
- retrieved and an implementation specific non-zero key value that specifies the end of the performance
- log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
- is retrieved and zero is returned. In the cases where a performance log entry can be returned,
- the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
- If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
- If Handle is NULL, then ASSERT().
- If Token is NULL, then ASSERT().
- If Module is NULL, then ASSERT().
- If StartTimeStamp is NULL, then ASSERT().
- If EndTimeStamp is NULL, then ASSERT().
- If Identifier is NULL, then ASSERT().
-
- @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
- 0, then the first performance measurement log entry is retrieved.
- On exit, the key of the next performance log entry.
- @param Handle Pointer to environment specific context used to identify the component
- being measured.
- @param Token Pointer to a Null-terminated ASCII string that identifies the component
- being measured.
- @param Module Pointer to a Null-terminated ASCII string that identifies the module
- being measured.
- @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was started.
- @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was ended.
- @param Identifier Pointer to the 32-bit identifier that was recorded.
-
- @return The key for the next performance log entry (in general case).
-
-**/
-UINTN
-EFIAPI
-GetPerformanceMeasurementEx (
- IN UINTN LogEntryKey,
- OUT CONST VOID **Handle,
- OUT CONST CHAR8 **Token,
- OUT CONST CHAR8 **Module,
- OUT UINT64 *StartTimeStamp,
- OUT UINT64 *EndTimeStamp,
- OUT UINT32 *Identifier
- )
-{
- return 0;
-}
-
-/**
- Adds a record at the end of the performance measurement log
- that records the start time of a performance measurement.
-
- Adds a record to the end of the performance measurement log
- that contains the Handle, Token, and Module.
- The end time of the new record must be set to zero.
- If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record.
- If TimeStamp is zero, the start time in the record is filled in with the value
- read from the current time stamp.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
-
- @retval RETURN_SUCCESS The start of the measurement was recorded.
- @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
-
-**/
-RETURN_STATUS
-EFIAPI
-StartPerformanceMeasurement (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp
- )
-{
- return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
- Searches the performance measurement log from the beginning of the log
- for the first matching record that contains a zero end time and fills in a valid end time.
-
- Searches the performance measurement log from the beginning of the log
- for the first record that matches Handle, Token, and Module and has an end time value of zero.
- If the record can not be found then return RETURN_NOT_FOUND.
- If the record is found and TimeStamp is not zero,
- then the end time in the record is filled in with the value specified by TimeStamp.
- If the record is found and TimeStamp is zero, then the end time in the matching record
- is filled in with the current time stamp value.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
-
- @retval RETURN_SUCCESS The end of the measurement was recorded.
- @retval RETURN_NOT_FOUND The specified measurement record could not be found.
-
-**/
-RETURN_STATUS
-EFIAPI
-EndPerformanceMeasurement (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp
- )
-{
- return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
- Attempts to retrieve a performance measurement log entry from the performance measurement log.
- It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
- and then eliminate the Identifier.
-
- !!! Not Support!!!
-
- Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
- zero on entry, then an attempt is made to retrieve the first entry from the performance log,
- and the key for the second entry in the log is returned. If the performance log is empty,
- then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
- log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
- returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
- retrieved and an implementation specific non-zero key value that specifies the end of the performance
- log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
- is retrieved and zero is returned. In the cases where a performance log entry can be returned,
- the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
- If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
- If Handle is NULL, then ASSERT().
- If Token is NULL, then ASSERT().
- If Module is NULL, then ASSERT().
- If StartTimeStamp is NULL, then ASSERT().
- If EndTimeStamp is NULL, then ASSERT().
-
- @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
- 0, then the first performance measurement log entry is retrieved.
- On exit, the key of the next performance log entry.
- @param Handle Pointer to environment specific context used to identify the component
- being measured.
- @param Token Pointer to a Null-terminated ASCII string that identifies the component
- being measured.
- @param Module Pointer to a Null-terminated ASCII string that identifies the module
- being measured.
- @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was started.
- @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was ended.
-
- @return The key for the next performance log entry (in general case).
-
-**/
-UINTN
-EFIAPI
-GetPerformanceMeasurement (
- IN UINTN LogEntryKey,
- OUT CONST VOID **Handle,
- OUT CONST CHAR8 **Token,
- OUT CONST CHAR8 **Module,
- OUT UINT64 *StartTimeStamp,
- OUT UINT64 *EndTimeStamp
- )
-{
- return 0;
-}
-
-/**
- Returns TRUE if the performance measurement macros are enabled.
-
- This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
- PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
-
- @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
- PcdPerformanceLibraryPropertyMask is set.
- @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
- PcdPerformanceLibraryPropertyMask is clear.
-
-**/
-BOOLEAN
-EFIAPI
-PerformanceMeasurementEnabled (
- VOID
- )
-{
- return mPerformanceMeasurementEnabled;
-}
-
-/**
- Create performance record with event description and a timestamp.
-
- @param CallerIdentifier - Image handle or pointer to caller ID GUID
- @param Guid - Pointer to a GUID
- @param String - Pointer to a string describing the measurement
- @param Address - Pointer to a location in memory relevant to the measurement
- @param Identifier - Performance identifier describing the type of measurement
-
- @retval RETURN_SUCCESS - Successfully created performance record
- @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
- @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
- pointer or invalid PerfId
-
-**/
-RETURN_STATUS
-EFIAPI
-LogPerformanceMeasurement (
- IN CONST VOID *CallerIdentifier,
- IN CONST VOID *Guid OPTIONAL,
- IN CONST CHAR8 *String OPTIONAL,
- IN UINT64 Address OPTIONAL,
- IN UINT32 Identifier
- )
-{
- return (RETURN_STATUS)CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
-}
-
-/**
- Check whether the specified performance measurement can be logged.
-
- This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
- and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
-
- @param Type - Type of the performance measurement entry.
-
- @retval TRUE The performance measurement can be logged.
- @retval FALSE The performance measurement can NOT be logged.
-
-**/
-BOOLEAN
-EFIAPI
-LogPerformanceMeasurementEnabled (
- IN CONST UINTN Type
- )
-{
- //
- // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
- //
- if (PerformanceMeasurementEnabled () && ((PcdGet8 (PcdPerformanceLibraryPropertyMask) & Type) == 0)) {
- return TRUE;
- }
-
- return FALSE;
-}
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
index 9a7e14e..b922463 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
@@ -9,18 +9,19 @@
# SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase.
#
# Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
- INF_VERSION = 0x00010005
+ INF_VERSION = 0x0001001B
BASE_NAME = SmmCorePerformanceLib
MODULE_UNI_FILE = SmmCorePerformanceLib.uni
FILE_GUID = 36290D10-0F47-42c1-BBCE-E191C7928DCF
MODULE_TYPE = SMM_CORE
VERSION_STRING = 1.0
- PI_SPECIFICATION_VERSION = 0x0001000A
+ PI_SPECIFICATION_VERSION = 0x00010032
LIBRARY_CLASS = PerformanceLib|SMM_CORE
CONSTRUCTOR = SmmCorePerformanceLibConstructor
@@ -32,33 +33,33 @@
#
[Sources]
- SmmCorePerformanceLib.c
+ MmCorePerformanceLib.c
SmmCorePerformanceLibInternal.h
+ SmmCorePerformanceLib.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
-
[LibraryClasses]
- MemoryAllocationLib
- UefiBootServicesTableLib
- PcdLib
- TimerLib
- BaseMemoryLib
BaseLib
+ BaseMemoryLib
DebugLib
- SynchronizationLib
- SmmServicesTableLib
+ DxeServicesLib
+ MemoryAllocationLib
+ PcdLib
+ PeCoffGetEntryPointLib
SmmMemLib
+ SmmServicesTableLib
+ SynchronizationLib
+ TimerLib
+ UefiBootServicesTableLib
UefiLib
- ReportStatusCodeLib
- PeCoffGetEntryPointLib
- DxeServicesLib
[Protocols]
gEfiSmmBase2ProtocolGuid ## CONSUMES
- gEdkiiSmmExitBootServicesProtocolGuid ## CONSUMES
+ gEdkiiSmmExitBootServicesProtocolGuid ## CONSUMES ## NOTIFY
+ gEfiLoadedImageProtocolGuid ## CONSUMES
[Guids]
## PRODUCES ## SystemTable
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
index 62b4964..bc1757c 100644
--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLibInternal.h
@@ -5,6 +5,7 @@
library instance at its constructor.
Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -12,32 +13,185 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#ifndef _SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_
#define _SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_
-#include <Guid/Performance.h>
-#include <Guid/PerformanceMeasurement.h>
+#include <Guid/EventGroup.h>
#include <Guid/ExtendedFirmwarePerformance.h>
#include <Guid/FirmwarePerformance.h>
+#include <Guid/Performance.h>
+#include <Guid/PerformanceMeasurement.h>
#include <Guid/ZeroGuid.h>
-#include <Guid/EventGroup.h>
-#include <Library/SmmServicesTableLib.h>
-#include <Library/DebugLib.h>
-#include <Library/PerformanceLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
-#include <Library/TimerLib.h>
-#include <Library/PcdLib.h>
-#include <Library/UefiLib.h>
-#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
-#include <Library/SynchronizationLib.h>
-#include <Library/SmmMemLib.h>
-#include <Library/ReportStatusCodeLib.h>
-#include <Library/DxeServicesLib.h>
+#include <Library/PcdLib.h>
#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/SmmMemLib.h>
+#include <Library/SynchronizationLib.h>
+#include <Library/TimerLib.h>
-#include <Protocol/SmmBase2.h>
-#include <Protocol/LoadedImage.h>
#include <Protocol/DevicePathToText.h>
+#include <Protocol/LoadedImage.h>
+
+#define STRING_SIZE (FPDT_STRING_EVENT_RECORD_NAME_LENGTH * sizeof (CHAR8))
+#define FIRMWARE_RECORD_BUFFER 0x1000
+#define CACHE_HANDLE_GUID_COUNT 0x100
+
+extern BOOLEAN mPerformanceMeasurementEnabled;
+
+//
+// Library internal function declarations
+//
+
+/**
+ Communication service SMI Handler entry.
+
+ This SMI handler provides services for report MM boot records.
+
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param[in] RegisterContext Points to an optional handler context which was specified when the
+ handler was registered.
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-MM environment into an MM environment.
+ @param[in, out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
+ should still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
+ still be called.
+ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
+ be called.
+ @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
+
+**/
+EFI_STATUS
+EFIAPI
+FpdtSmiHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *RegisterContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ );
+
+/**
+ This is the Event call back function is triggered in SMM to notify the Library
+ the system is entering runtime phase.
+
+ @param[in] Protocol Points to the protocol's unique identifier
+ @param[in] Interface Points to the interface instance
+ @param[in] Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
+ **/
+EFI_STATUS
+EFIAPI
+SmmCorePerformanceLibExitBootServicesCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ Return a pointer to the loaded image protocol for the given handle.
+
+ @param[in] Handle A handle to query for the loaded image protocol.
+
+ @return A pointer to a loaded image protocol instance or null if the handle does not support load image protocol.
+**/
+EFI_LOADED_IMAGE_PROTOCOL *
+GetLoadedImageProtocol (
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ Get the module name from the PDB file name in the image header.
+
+ @param[in] ImageBase The base address of the image.
+ @param[out] NameString The buffer to store the name string.
+ @param[in] BufferSize The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The name string is successfully retrieved.
+ @retval EFI_INVALID_PARAMETER A pointer argument provided is null.
+ @retval EFI_NOT_FOUND The module name was not found.
+
+**/
+EFI_STATUS
+GetModuleNameFromPdbString (
+ IN VOID *ImageBase,
+ OUT CHAR8 *NameString,
+ IN UINTN BufferSize
+ );
+
+/**
+ Get the module name from the user interface section.
+
+ @param[in] ModuleGuid The GUID of the module.
+ @param[out] NameString The buffer to store the name string.
+ @param[in] BufferSize The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The name string is successfully retrieved.
+ @retval EFI_NOT_FOUND The module name was not found.
+
+**/
+EFI_STATUS
+GetNameFromUiSection (
+ IN EFI_GUID *ModuleGuid,
+ OUT CHAR8 *NameString,
+ IN UINTN BufferSize
+ );
+
+/**
+ Common initialization code for the MM Core Performance Library.
+
+ @param[in] ExitBootServicesProtocolGuid The GUID of the ExitBootServices protocol.
+
+ @retval EFI_SUCCESS The MM Core Performance Library was initialized successfully.
+ @retval Others The MM Core Performance Library was not initialized successfully.
+ **/
+EFI_STATUS
+InitializeMmCorePerformanceLibCommon (
+ IN CONST EFI_GUID *ExitBootServicesProtocolGuid
+ );
+
+/**
+ A library internal MM-instance specific implementation to check if a buffer outside MM is valid.
+
+ This function is provided so Standalone MM and Traditional MM may use a different implementation
+ of data buffer check logic.
+
+ @param[in] Buffer The buffer start address to be checked.
+ @param[in] Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture.
+ @retval FALSE This buffer is not valid per processor architecture.
+**/
+BOOLEAN
+MmCorePerformanceIsNonPrimaryBufferValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ );
+
+/**
+ A library internal MM-instance specific implementation to check if a comm buffer is valid.
+
+ This function is provided so Standalone MM and Traditional MM may use a different implementation
+ of comm buffer check logic.
+
+ @param[in] Buffer The buffer start address to be checked.
+ @param[in] Length The buffer length to be checked.
+
+ @retval TRUE This communicate buffer is valid per processor architecture.
+ @retval FALSE This communicate buffer is not valid per processor architecture.
+**/
+BOOLEAN
+MmCorePerformanceIsPrimaryBufferValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ );
//
// Interface declarations for SMM PerformanceMeasurement Protocol.
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.c
new file mode 100644
index 0000000..55ec507
--- /dev/null
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.c
@@ -0,0 +1,208 @@
+/** @file
+ This library is mainly used by the Standalone MM Core to start performance logging to ensure that
+ Standalone MM Performance and PerformanceEx Protocol are installed as early as possible in the MM phase.
+
+ Caution: This module requires additional review when modified.
+ - This driver will have external input - performance data and communicate buffer in MM mode.
+ - This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmmCorePerformanceLibInternal.h"
+
+#include <Guid/EventGroup.h>
+#include <Library/MmServicesTableLib.h>
+#include <Library/StandaloneMmMemLib.h>
+
+extern SPIN_LOCK mSmmFpdtLock;
+
+EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL mPerformanceMeasurementInterface = {
+ CreatePerformanceMeasurement,
+};
+
+/**
+ A library internal MM-instance specific implementation to check if a buffer outside MM is valid.
+
+ This function is provided so Standalone MM and Traditional MM may use a different implementation
+ of data buffer check logic.
+
+ @param[in] Buffer The buffer start address to be checked.
+ @param[in] Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture.
+ @retval FALSE This buffer is not valid per processor architecture.
+**/
+BOOLEAN
+MmCorePerformanceIsNonPrimaryBufferValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return MmIsBufferOutsideMmValid (Buffer, Length);
+}
+
+/**
+ A library internal MM-instance specific implementation to check if a comm buffer is valid.
+
+ This function is provided so Standalone MM and Traditional MM may use a different implementation
+ of comm buffer check logic.
+
+ @param[in] Buffer The buffer start address to be checked.
+ @param[in] Length The buffer length to be checked.
+
+ @retval TRUE This communicate buffer is valid per processor architecture.
+ @retval FALSE This communicate buffer is not valid per processor architecture.
+**/
+BOOLEAN
+MmCorePerformanceIsPrimaryBufferValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return TRUE;
+}
+
+/**
+ Return a pointer to the loaded image protocol for the given handle.
+
+ @param[in] Handle A handle to query for the loaded image protocol.
+
+ @return A pointer to a loaded image protocol instance or null if the handle does not support load image protocol.
+**/
+EFI_LOADED_IMAGE_PROTOCOL *
+GetLoadedImageProtocol (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+
+ if (Handle == NULL) {
+ return NULL;
+ }
+
+ LoadedImage = NULL;
+ gMmst->MmHandleProtocol (
+ Handle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ return LoadedImage;
+}
+
+/**
+ Get the module name from the user interface section.
+
+ @param[in] ModuleGuid The GUID of the module.
+ @param[out] NameString The buffer to store the name string.
+ @param[in] BufferSize The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The name string is successfully retrieved.
+ @retval EFI_NOT_FOUND The module name was not found.
+
+**/
+EFI_STATUS
+GetNameFromUiSection (
+ IN EFI_GUID *ModuleGuid,
+ OUT CHAR8 *NameString,
+ IN UINTN BufferSize
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Initializes the MM Core Performance library.
+
+ @retval EFI_SUCCESS The performance library was initialized successfully.
+ @retval Other An error occurred during initialization.
+**/
+EFI_STATUS
+EFIAPI
+InitializeStandaloneMmCorePerformanceLib (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_HANDLE MmiHandle;
+ VOID *Registration;
+
+ //
+ // Initialize spin lock
+ //
+ InitializeSpinLock (&mSmmFpdtLock);
+ //
+ // Install the protocol interfaces for MM performance library instance.
+ //
+ Handle = NULL;
+ Status = gMmst->MmInstallProtocolInterface (
+ &Handle,
+ &gEdkiiSmmPerformanceMeasurementProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mPerformanceMeasurementInterface
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register MMI handler.
+ //
+ MmiHandle = NULL;
+ Status = gMmst->MmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &MmiHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Register callback function for ExitBootServices event.
+ //
+ Status = gMmst->MmRegisterProtocolNotify (
+ &gEfiEventExitBootServicesGuid,
+ SmmCorePerformanceLibExitBootServicesCallback,
+ &Registration
+ );
+
+ return Status;
+}
+
+/**
+ The constructor function initializes the Standalone MM Core performance library.
+
+ It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS.
+
+ @param[in] ImageHandle The firmware allocated handle for the image.
+ @param[in] MmSystemTable A pointer to the MM System Table.
+
+ @retval EFI_SUCCESS The constructor successfully gets HobList.
+ @retval Other value The constructor can't get HobList.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmCorePerformanceLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mPerformanceMeasurementEnabled = (BOOLEAN)((FixedPcdGet8 (PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
+
+ if (!PerformanceMeasurementEnabled ()) {
+ DEBUG ((DEBUG_WARN, "[%a] - Performance library is linked but performance tracing is not enabled.\n", __func__));
+ //
+ // Do not initialize performance infrastructure if not required.
+ //
+ return EFI_SUCCESS;
+ }
+
+ Status = InitializeStandaloneMmCorePerformanceLib ();
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf b/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf
new file mode 100644
index 0000000..87ce20e
--- /dev/null
+++ b/MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf
@@ -0,0 +1,55 @@
+## @file
+# Performance library instance used by a Standalone MM Core or an early Standlaone MM module that
+# should install performance measurement services.
+#
+# Installs the MM performance measurement protocol and returns MM performance data via MM communicate.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = StandaloneMmCorePerformanceLib
+ FILE_GUID = 8585D462-DE63-4080-882A-A73974CE5609
+ MODULE_TYPE = MM_CORE_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = PerformanceLib|MM_CORE_STANDALONE MM_STANDALONE
+ CONSTRUCTOR = StandaloneMmCorePerformanceLibConstructor
+
+[Sources]
+ MmCorePerformanceLib.c
+ SmmCorePerformanceLibInternal.h
+ StandaloneMmCorePerformanceLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ MemLib
+ MmServicesTableLib
+ PcdLib
+ PeCoffGetEntryPointLib
+ SynchronizationLib
+ TimerLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiFirmwarePerformanceGuid ## SOMETIMES_PRODUCES # SmiHandlerRegister
+ gEdkiiSmmPerformanceMeasurementProtocolGuid ## PRODUCES # Install protocol
+ gZeroGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiEventExitBootServicesGuid ## CONSUMES ## NOTIFY
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEdkiiFpdtStringRecordEnableOnly ## CONSUMES
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
index 9782326..8000e64 100644
--- a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.c
@@ -7,58 +7,20 @@
performance information.
Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <Guid/PerformanceMeasurement.h>
-
-#include <Library/PerformanceLib.h>
-#include <Library/DebugLib.h>
-#include <Library/SmmServicesTableLib.h>
-#include <Library/PcdLib.h>
-#include <Library/BaseMemoryLib.h>
-
-//
-// The cached SMM Performance Protocol and SMM PerformanceEx Protocol interface.
-EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL *mPerformanceMeasurement = NULL;
-BOOLEAN mPerformanceMeasurementEnabled;
-VOID *mPerformanceLibExitBootServicesRegistration;
-
-/**
- This is the Event call back function is triggered in SMM to notify the Library
- the system is entering runtime phase.
-
- @param[in] Protocol Points to the protocol's unique identifier
- @param[in] Interface Points to the interface instance
- @param[in] Handle The handle on which the interface was installed
-
- @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
- **/
-EFI_STATUS
-EFIAPI
-SmmPerformanceLibExitBootServicesCallback (
- IN CONST EFI_GUID *Protocol,
- IN VOID *Interface,
- IN EFI_HANDLE Handle
- )
-{
- //
- // Disable performance measurement after ExitBootServices because
- // 1. Performance measurement might impact SMI latency at runtime;
- // 2. Performance log is copied to non SMRAM at ReadyToBoot so runtime performance
- // log is not useful.
- //
- mPerformanceMeasurementEnabled = FALSE;
-
- return EFI_SUCCESS;
-}
+#include <PiMm.h>
+#include <Protocol/SmmExitBootServices.h>
+#include "SmmPerformanceLibInternal.h"
/**
- The constructor function initializes the Performance Measurement Enable flag
+ The constructor function initializes the Performance Measurement Enable flag.
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
@@ -70,27 +32,17 @@ SmmPerformanceLibConstructor (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
-
- mPerformanceMeasurementEnabled = (BOOLEAN)((PcdGet8 (PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
-
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEdkiiSmmExitBootServicesProtocolGuid,
- SmmPerformanceLibExitBootServicesCallback,
- &mPerformanceLibExitBootServicesRegistration
- );
- ASSERT_EFI_ERROR (Status);
-
- return Status;
+ return RegisterExitBootServicesCallback (&gEdkiiSmmExitBootServicesProtocolGuid);
}
/**
The destructor function frees resources allocated by constructor.
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The destructor always returns EFI_SUCCESS.
+
**/
EFI_STATUS
EFIAPI
@@ -99,432 +51,5 @@ SmmPerformanceLibDestructor (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
-
- //
- // Unregister SmmExitBootServices notification.
- //
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEdkiiSmmExitBootServicesProtocolGuid,
- NULL,
- &mPerformanceLibExitBootServicesRegistration
- );
- ASSERT_EFI_ERROR (Status);
-
- return Status;
-}
-
-/**
- The function caches the pointers to SMM PerformanceEx protocol and Performance Protocol.
-
- The function locates SMM PerformanceEx protocol and Performance Protocol from protocol database.
-
- @retval EFI_SUCCESS SMM PerformanceEx protocol or Performance Protocol is successfully located.
- @retval EFI_NOT_FOUND Both SMM PerformanceEx protocol and Performance Protocol are not located to log performance.
-
-**/
-EFI_STATUS
-GetPerformanceMeasurementProtocol (
- VOID
- )
-{
- EFI_STATUS Status;
- EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL *PerformanceMeasurement;
-
- if (mPerformanceMeasurement != NULL) {
- return EFI_SUCCESS;
- }
-
- Status = gSmst->SmmLocateProtocol (&gEdkiiSmmPerformanceMeasurementProtocolGuid, NULL, (VOID **)&PerformanceMeasurement);
- if (!EFI_ERROR (Status)) {
- ASSERT (PerformanceMeasurement != NULL);
- //
- // Cache PerformanceMeasurement Protocol.
- //
- mPerformanceMeasurement = PerformanceMeasurement;
- return EFI_SUCCESS;
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Creates a record for the beginning of a performance measurement.
-
- Creates a record that contains the Handle, Token, Module and Identifier.
- If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
- If TimeStamp is zero, then this function reads the current time stamp
- and adds that time stamp value to the record as the start time.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
- @param Identifier 32-bit identifier. If the value is 0, the created record
- is same as the one created by StartPerformanceMeasurement.
-
- @retval RETURN_SUCCESS The start of the measurement was recorded.
- @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
-
-**/
-RETURN_STATUS
-EFIAPI
-StartPerformanceMeasurementEx (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp,
- IN UINT32 Identifier
- )
-{
- EFI_STATUS Status;
- CONST CHAR8 *String;
-
- Status = GetPerformanceMeasurementProtocol ();
- if (EFI_ERROR (Status)) {
- return RETURN_NOT_FOUND;
- }
-
- if (Token != NULL) {
- String = Token;
- } else if (Module != NULL) {
- String = Module;
- } else {
- String = NULL;
- }
-
- if (mPerformanceMeasurement != NULL) {
- Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
- } else {
- ASSERT (FALSE);
- }
-
- return (RETURN_STATUS)Status;
-}
-
-/**
- Fills in the end time of a performance measurement.
-
- Looks up the record that matches Handle, Token and Module.
- If the record can not be found then return RETURN_NOT_FOUND.
- If the record is found and TimeStamp is not zero,
- then TimeStamp is added to the record as the end time.
- If the record is found and TimeStamp is zero, then this function reads
- the current time stamp and adds that time stamp value to the record as the end time.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
- @param Identifier 32-bit identifier. If the value is 0, the found record
- is same as the one found by EndPerformanceMeasurement.
-
- @retval RETURN_SUCCESS The end of the measurement was recorded.
- @retval RETURN_NOT_FOUND The specified measurement record could not be found.
-
-**/
-RETURN_STATUS
-EFIAPI
-EndPerformanceMeasurementEx (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp,
- IN UINT32 Identifier
- )
-{
- EFI_STATUS Status;
- CONST CHAR8 *String;
-
- Status = GetPerformanceMeasurementProtocol ();
- if (EFI_ERROR (Status)) {
- return RETURN_NOT_FOUND;
- }
-
- if (Token != NULL) {
- String = Token;
- } else if (Module != NULL) {
- String = Module;
- } else {
- String = NULL;
- }
-
- if (mPerformanceMeasurement != NULL) {
- Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
- } else {
- ASSERT (FALSE);
- }
-
- return (RETURN_STATUS)Status;
-}
-
-/**
- Attempts to retrieve a performance measurement log entry from the performance measurement log.
- It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
- and then assign the Identifier with 0.
-
- Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
- zero on entry, then an attempt is made to retrieve the first entry from the performance log,
- and the key for the second entry in the log is returned. If the performance log is empty,
- then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
- log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
- returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
- retrieved and an implementation specific non-zero key value that specifies the end of the performance
- log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
- is retrieved and zero is returned. In the cases where a performance log entry can be returned,
- the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
- If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
- If Handle is NULL, then ASSERT().
- If Token is NULL, then ASSERT().
- If Module is NULL, then ASSERT().
- If StartTimeStamp is NULL, then ASSERT().
- If EndTimeStamp is NULL, then ASSERT().
- If Identifier is NULL, then ASSERT().
-
- @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
- 0, then the first performance measurement log entry is retrieved.
- On exit, the key of the next performance log entry.
- @param Handle Pointer to environment specific context used to identify the component
- being measured.
- @param Token Pointer to a Null-terminated ASCII string that identifies the component
- being measured.
- @param Module Pointer to a Null-terminated ASCII string that identifies the module
- being measured.
- @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was started.
- @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was ended.
- @param Identifier Pointer to the 32-bit identifier that was recorded.
-
- @return The key for the next performance log entry (in general case).
-
-**/
-UINTN
-EFIAPI
-GetPerformanceMeasurementEx (
- IN UINTN LogEntryKey,
- OUT CONST VOID **Handle,
- OUT CONST CHAR8 **Token,
- OUT CONST CHAR8 **Module,
- OUT UINT64 *StartTimeStamp,
- OUT UINT64 *EndTimeStamp,
- OUT UINT32 *Identifier
- )
-{
- return 0;
-}
-
-/**
- Creates a record for the beginning of a performance measurement.
-
- Creates a record that contains the Handle, Token, and Module.
- If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
- If TimeStamp is zero, then this function reads the current time stamp
- and adds that time stamp value to the record as the start time.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
-
- @retval RETURN_SUCCESS The start of the measurement was recorded.
- @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
-
-**/
-RETURN_STATUS
-EFIAPI
-StartPerformanceMeasurement (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp
- )
-{
- return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
- Fills in the end time of a performance measurement.
-
- Looks up the record that matches Handle, Token, and Module.
- If the record can not be found then return RETURN_NOT_FOUND.
- If the record is found and TimeStamp is not zero,
- then TimeStamp is added to the record as the end time.
- If the record is found and TimeStamp is zero, then this function reads
- the current time stamp and adds that time stamp value to the record as the end time.
-
- @param Handle Pointer to environment specific context used
- to identify the component being measured.
- @param Token Pointer to a Null-terminated ASCII string
- that identifies the component being measured.
- @param Module Pointer to a Null-terminated ASCII string
- that identifies the module being measured.
- @param TimeStamp 64-bit time stamp.
-
- @retval RETURN_SUCCESS The end of the measurement was recorded.
- @retval RETURN_NOT_FOUND The specified measurement record could not be found.
-
-**/
-RETURN_STATUS
-EFIAPI
-EndPerformanceMeasurement (
- IN CONST VOID *Handle OPTIONAL,
- IN CONST CHAR8 *Token OPTIONAL,
- IN CONST CHAR8 *Module OPTIONAL,
- IN UINT64 TimeStamp
- )
-{
- return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
-}
-
-/**
- Attempts to retrieve a performance measurement log entry from the performance measurement log.
- It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
- and then eliminate the Identifier.
-
- Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
- zero on entry, then an attempt is made to retrieve the first entry from the performance log,
- and the key for the second entry in the log is returned. If the performance log is empty,
- then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
- log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
- returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
- retrieved and an implementation specific non-zero key value that specifies the end of the performance
- log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
- is retrieved and zero is returned. In the cases where a performance log entry can be returned,
- the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
- If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
- If Handle is NULL, then ASSERT().
- If Token is NULL, then ASSERT().
- If Module is NULL, then ASSERT().
- If StartTimeStamp is NULL, then ASSERT().
- If EndTimeStamp is NULL, then ASSERT().
-
- @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
- 0, then the first performance measurement log entry is retrieved.
- On exit, the key of the next performance log entry.
- @param Handle Pointer to environment specific context used to identify the component
- being measured.
- @param Token Pointer to a Null-terminated ASCII string that identifies the component
- being measured.
- @param Module Pointer to a Null-terminated ASCII string that identifies the module
- being measured.
- @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was started.
- @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
- was ended.
-
- @return The key for the next performance log entry (in general case).
-
-**/
-UINTN
-EFIAPI
-GetPerformanceMeasurement (
- IN UINTN LogEntryKey,
- OUT CONST VOID **Handle,
- OUT CONST CHAR8 **Token,
- OUT CONST CHAR8 **Module,
- OUT UINT64 *StartTimeStamp,
- OUT UINT64 *EndTimeStamp
- )
-{
- return 0;
-}
-
-/**
- Returns TRUE if the performance measurement macros are enabled.
-
- This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
- PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
-
- @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
- PcdPerformanceLibraryPropertyMask is set.
- @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
- PcdPerformanceLibraryPropertyMask is clear.
-
-**/
-BOOLEAN
-EFIAPI
-PerformanceMeasurementEnabled (
- VOID
- )
-{
- return mPerformanceMeasurementEnabled;
-}
-
-/**
- Create performance record with event description and a timestamp.
-
- @param CallerIdentifier - Image handle or pointer to caller ID GUID
- @param Guid - Pointer to a GUID
- @param String - Pointer to a string describing the measurement
- @param Address - Pointer to a location in memory relevant to the measurement
- @param Identifier - Performance identifier describing the type of measurement
-
- @retval RETURN_SUCCESS - Successfully created performance record
- @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
- @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
- pointer or invalid PerfId
-
-**/
-RETURN_STATUS
-EFIAPI
-LogPerformanceMeasurement (
- IN CONST VOID *CallerIdentifier,
- IN CONST VOID *Guid OPTIONAL,
- IN CONST CHAR8 *String OPTIONAL,
- IN UINT64 Address OPTIONAL,
- IN UINT32 Identifier
- )
-{
- EFI_STATUS Status;
-
- Status = GetPerformanceMeasurementProtocol ();
- if (EFI_ERROR (Status)) {
- return RETURN_OUT_OF_RESOURCES;
- }
-
- if (mPerformanceMeasurement != NULL) {
- Status = mPerformanceMeasurement->CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
- } else {
- ASSERT (FALSE);
- }
-
- return (RETURN_STATUS)Status;
-}
-
-/**
- Check whether the specified performance measurement can be logged.
-
- This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
- and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
-
- @param Type - Type of the performance measurement entry.
-
- @retval TRUE The performance measurement can be logged.
- @retval FALSE The performance measurement can NOT be logged.
-
-**/
-BOOLEAN
-EFIAPI
-LogPerformanceMeasurementEnabled (
- IN CONST UINTN Type
- )
-{
- //
- // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
- //
- if (PerformanceMeasurementEnabled () && ((PcdGet8 (PcdPerformanceLibraryPropertyMask) & Type) == 0)) {
- return TRUE;
- }
-
- return FALSE;
+ return UnregisterExitBootServicesCallback (&gEdkiiSmmExitBootServicesProtocolGuid);
}
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
index 002462f..81f423a 100644
--- a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
@@ -7,6 +7,7 @@
# it does not log any performance information.
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -30,6 +31,8 @@
#
[Sources]
+ SmmPerformanceLibInternal.h
+ SmmPerformanceLibInternal.c
SmmPerformanceLib.c
@@ -40,7 +43,7 @@
[LibraryClasses]
PcdLib
- SmmServicesTableLib
+ MmServicesTableLib
DebugLib
BaseMemoryLib
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.c b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.c
new file mode 100644
index 0000000..f9bafca
--- /dev/null
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.c
@@ -0,0 +1,529 @@
+/** @file
+ Performance Library used in the MM phase.
+
+ This library instance provides infrastructure for MM drivers to log performance
+ data. It consumes MM PerformanceEx or Performance Protocol published by SmmCorePerformanceLib
+ to log performance data. If both MM PerformanceEx and Performance Protocol are not available,
+ it does not log any performance information.
+
+ Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Guid/PerformanceMeasurement.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PerformanceLib.h>
+
+#include "SmmPerformanceLibInternal.h"
+
+//
+// The cached MM Performance Protocol and MM PerformanceEx Protocol interface.
+EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL *mPerformanceMeasurement = NULL;
+BOOLEAN mPerformanceMeasurementEnabled;
+VOID *mPerformanceLibExitBootServicesRegistration;
+
+/**
+ Registers a callback to perform library actions needed at exit boot services.
+
+ @param[in] ExitBootServicesProtocolGuid The protocol GUID to register the callback for.
+
+ @retval EFI_SUCCESS The callback was registered successfully.
+ @retval Others An error occurred registering the callback.
+ **/
+EFI_STATUS
+RegisterExitBootServicesCallback (
+ IN CONST EFI_GUID *ExitBootServicesProtocolGuid
+ )
+{
+ EFI_STATUS Status;
+
+ mPerformanceMeasurementEnabled = (BOOLEAN)((PcdGet8 (PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0);
+
+ Status = gMmst->MmRegisterProtocolNotify (
+ ExitBootServicesProtocolGuid,
+ SmmPerformanceLibExitBootServicesCallback,
+ &mPerformanceLibExitBootServicesRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Unregisters a callback to perform library actions needed at exit boot services.
+
+ @param[in] ExitBootServicesProtocolGuid The protocol GUID to unregister the callback for.
+
+ @retval EFI_SUCCESS The callback was unregistered successfully.
+ @retval Others An error occurred unregistering the callback.
+ **/
+EFI_STATUS
+UnregisterExitBootServicesCallback (
+ IN CONST EFI_GUID *ExitBootServicesProtocolGuid
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Unregister SmmExitBootServices notification.
+ //
+ Status = gMmst->MmRegisterProtocolNotify (
+ ExitBootServicesProtocolGuid,
+ NULL,
+ &mPerformanceLibExitBootServicesRegistration
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ This is the Event call back function is triggered in MM to notify the Library
+ the system is entering runtime phase.
+
+ @param[in] Protocol Points to the protocol's unique identifier
+ @param[in] Interface Points to the interface instance
+ @param[in] Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
+ **/
+EFI_STATUS
+EFIAPI
+SmmPerformanceLibExitBootServicesCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ )
+{
+ //
+ // Disable performance measurement after ExitBootServices because
+ // 1. Performance measurement might impact SMI latency at runtime;
+ // 2. Performance log is copied to non SMRAM at ReadyToBoot so runtime performance
+ // log is not useful.
+ //
+ mPerformanceMeasurementEnabled = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The function caches the pointers to MM PerformanceEx protocol and Performance Protocol.
+
+ The function locates MM PerformanceEx protocol and Performance Protocol from protocol database.
+
+ @retval EFI_SUCCESS MM PerformanceEx protocol or Performance Protocol is successfully located.
+ @retval EFI_NOT_FOUND Both MM PerformanceEx protocol and Performance Protocol are not located to log performance.
+
+**/
+EFI_STATUS
+GetPerformanceMeasurementProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EDKII_PERFORMANCE_MEASUREMENT_PROTOCOL *PerformanceMeasurement;
+
+ if (mPerformanceMeasurement != NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gMmst->MmLocateProtocol (&gEdkiiSmmPerformanceMeasurementProtocolGuid, NULL, (VOID **)&PerformanceMeasurement);
+ if (!EFI_ERROR (Status)) {
+ ASSERT (PerformanceMeasurement != NULL);
+
+ //
+ // Cache PerformanceMeasurement Protocol.
+ //
+ mPerformanceMeasurement = PerformanceMeasurement;
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Creates a record for the beginning of a performance measurement.
+
+ Creates a record that contains the Handle, Token, Module and Identifier.
+ If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
+ If TimeStamp is zero, then this function reads the current time stamp
+ and adds that time stamp value to the record as the start time.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+ @param Identifier 32-bit identifier. If the value is 0, the created record
+ is same as the one created by StartPerformanceMeasurement.
+
+ @retval RETURN_SUCCESS The start of the measurement was recorded.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
+
+**/
+RETURN_STATUS
+EFIAPI
+StartPerformanceMeasurementEx (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp,
+ IN UINT32 Identifier
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR8 *String;
+
+ Status = GetPerformanceMeasurementProtocol ();
+ if (EFI_ERROR (Status)) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (Token != NULL) {
+ String = Token;
+ } else if (Module != NULL) {
+ String = Module;
+ } else {
+ String = NULL;
+ }
+
+ if (mPerformanceMeasurement != NULL) {
+ Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfStartEntry);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return (RETURN_STATUS)Status;
+}
+
+/**
+ Fills in the end time of a performance measurement.
+
+ Looks up the record that matches Handle, Token and Module.
+ If the record can not be found then return RETURN_NOT_FOUND.
+ If the record is found and TimeStamp is not zero,
+ then TimeStamp is added to the record as the end time.
+ If the record is found and TimeStamp is zero, then this function reads
+ the current time stamp and adds that time stamp value to the record as the end time.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+ @param Identifier 32-bit identifier. If the value is 0, the found record
+ is same as the one found by EndPerformanceMeasurement.
+
+ @retval RETURN_SUCCESS The end of the measurement was recorded.
+ @retval RETURN_NOT_FOUND The specified measurement record could not be found.
+
+**/
+RETURN_STATUS
+EFIAPI
+EndPerformanceMeasurementEx (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp,
+ IN UINT32 Identifier
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR8 *String;
+
+ Status = GetPerformanceMeasurementProtocol ();
+ if (EFI_ERROR (Status)) {
+ return RETURN_NOT_FOUND;
+ }
+
+ if (Token != NULL) {
+ String = Token;
+ } else if (Module != NULL) {
+ String = Module;
+ } else {
+ String = NULL;
+ }
+
+ if (mPerformanceMeasurement != NULL) {
+ Status = mPerformanceMeasurement->CreatePerformanceMeasurement (Handle, NULL, String, TimeStamp, 0, Identifier, PerfEndEntry);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return (RETURN_STATUS)Status;
+}
+
+/**
+ Attempts to retrieve a performance measurement log entry from the performance measurement log.
+ It can also retrieve the log created by StartPerformanceMeasurement and EndPerformanceMeasurement,
+ and then assign the Identifier with 0.
+
+ Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
+ zero on entry, then an attempt is made to retrieve the first entry from the performance log,
+ and the key for the second entry in the log is returned. If the performance log is empty,
+ then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
+ log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
+ returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
+ retrieved and an implementation specific non-zero key value that specifies the end of the performance
+ log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
+ is retrieved and zero is returned. In the cases where a performance log entry can be returned,
+ the log entry is returned in Handle, Token, Module, StartTimeStamp, EndTimeStamp and Identifier.
+ If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
+ If Handle is NULL, then ASSERT().
+ If Token is NULL, then ASSERT().
+ If Module is NULL, then ASSERT().
+ If StartTimeStamp is NULL, then ASSERT().
+ If EndTimeStamp is NULL, then ASSERT().
+ If Identifier is NULL, then ASSERT().
+
+ @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
+ 0, then the first performance measurement log entry is retrieved.
+ On exit, the key of the next performance log entry.
+ @param Handle Pointer to environment specific context used to identify the component
+ being measured.
+ @param Token Pointer to a Null-terminated ASCII string that identifies the component
+ being measured.
+ @param Module Pointer to a Null-terminated ASCII string that identifies the module
+ being measured.
+ @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was started.
+ @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was ended.
+ @param Identifier Pointer to the 32-bit identifier that was recorded.
+
+ @return The key for the next performance log entry (in general case).
+
+**/
+UINTN
+EFIAPI
+GetPerformanceMeasurementEx (
+ IN UINTN LogEntryKey,
+ OUT CONST VOID **Handle,
+ OUT CONST CHAR8 **Token,
+ OUT CONST CHAR8 **Module,
+ OUT UINT64 *StartTimeStamp,
+ OUT UINT64 *EndTimeStamp,
+ OUT UINT32 *Identifier
+ )
+{
+ return 0;
+}
+
+/**
+ Creates a record for the beginning of a performance measurement.
+
+ Creates a record that contains the Handle, Token, and Module.
+ If TimeStamp is not zero, then TimeStamp is added to the record as the start time.
+ If TimeStamp is zero, then this function reads the current time stamp
+ and adds that time stamp value to the record as the start time.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+
+ @retval RETURN_SUCCESS The start of the measurement was recorded.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement.
+
+**/
+RETURN_STATUS
+EFIAPI
+StartPerformanceMeasurement (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp
+ )
+{
+ return StartPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
+}
+
+/**
+ Fills in the end time of a performance measurement.
+
+ Looks up the record that matches Handle, Token, and Module.
+ If the record can not be found then return RETURN_NOT_FOUND.
+ If the record is found and TimeStamp is not zero,
+ then TimeStamp is added to the record as the end time.
+ If the record is found and TimeStamp is zero, then this function reads
+ the current time stamp and adds that time stamp value to the record as the end time.
+
+ @param Handle Pointer to environment specific context used
+ to identify the component being measured.
+ @param Token Pointer to a Null-terminated ASCII string
+ that identifies the component being measured.
+ @param Module Pointer to a Null-terminated ASCII string
+ that identifies the module being measured.
+ @param TimeStamp 64-bit time stamp.
+
+ @retval RETURN_SUCCESS The end of the measurement was recorded.
+ @retval RETURN_NOT_FOUND The specified measurement record could not be found.
+
+**/
+RETURN_STATUS
+EFIAPI
+EndPerformanceMeasurement (
+ IN CONST VOID *Handle OPTIONAL,
+ IN CONST CHAR8 *Token OPTIONAL,
+ IN CONST CHAR8 *Module OPTIONAL,
+ IN UINT64 TimeStamp
+ )
+{
+ return EndPerformanceMeasurementEx (Handle, Token, Module, TimeStamp, 0);
+}
+
+/**
+ Attempts to retrieve a performance measurement log entry from the performance measurement log.
+ It can also retrieve the log created by StartPerformanceMeasurementEx and EndPerformanceMeasurementEx,
+ and then eliminate the Identifier.
+
+ Attempts to retrieve the performance log entry specified by LogEntryKey. If LogEntryKey is
+ zero on entry, then an attempt is made to retrieve the first entry from the performance log,
+ and the key for the second entry in the log is returned. If the performance log is empty,
+ then no entry is retrieved and zero is returned. If LogEntryKey is not zero, then the performance
+ log entry associated with LogEntryKey is retrieved, and the key for the next entry in the log is
+ returned. If LogEntryKey is the key for the last entry in the log, then the last log entry is
+ retrieved and an implementation specific non-zero key value that specifies the end of the performance
+ log is returned. If LogEntryKey is equal this implementation specific non-zero key value, then no entry
+ is retrieved and zero is returned. In the cases where a performance log entry can be returned,
+ the log entry is returned in Handle, Token, Module, StartTimeStamp, and EndTimeStamp.
+ If LogEntryKey is not a valid log entry key for the performance measurement log, then ASSERT().
+ If Handle is NULL, then ASSERT().
+ If Token is NULL, then ASSERT().
+ If Module is NULL, then ASSERT().
+ If StartTimeStamp is NULL, then ASSERT().
+ If EndTimeStamp is NULL, then ASSERT().
+
+ @param LogEntryKey On entry, the key of the performance measurement log entry to retrieve.
+ 0, then the first performance measurement log entry is retrieved.
+ On exit, the key of the next performance log entry.
+ @param Handle Pointer to environment specific context used to identify the component
+ being measured.
+ @param Token Pointer to a Null-terminated ASCII string that identifies the component
+ being measured.
+ @param Module Pointer to a Null-terminated ASCII string that identifies the module
+ being measured.
+ @param StartTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was started.
+ @param EndTimeStamp Pointer to the 64-bit time stamp that was recorded when the measurement
+ was ended.
+
+ @return The key for the next performance log entry (in general case).
+
+**/
+UINTN
+EFIAPI
+GetPerformanceMeasurement (
+ IN UINTN LogEntryKey,
+ OUT CONST VOID **Handle,
+ OUT CONST CHAR8 **Token,
+ OUT CONST CHAR8 **Module,
+ OUT UINT64 *StartTimeStamp,
+ OUT UINT64 *EndTimeStamp
+ )
+{
+ return 0;
+}
+
+/**
+ Returns TRUE if the performance measurement macros are enabled.
+
+ This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is set.
+ @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of
+ PcdPerformanceLibraryPropertyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+PerformanceMeasurementEnabled (
+ VOID
+ )
+{
+ return mPerformanceMeasurementEnabled;
+}
+
+/**
+ Create performance record with event description and a timestamp.
+
+ @param CallerIdentifier - Image handle or pointer to caller ID GUID
+ @param Guid - Pointer to a GUID
+ @param String - Pointer to a string describing the measurement
+ @param Address - Pointer to a location in memory relevant to the measurement
+ @param Identifier - Performance identifier describing the type of measurement
+
+ @retval RETURN_SUCCESS - Successfully created performance record
+ @retval RETURN_OUT_OF_RESOURCES - Ran out of space to store the records
+ @retval RETURN_INVALID_PARAMETER - Invalid parameter passed to function - NULL
+ pointer or invalid PerfId
+
+**/
+RETURN_STATUS
+EFIAPI
+LogPerformanceMeasurement (
+ IN CONST VOID *CallerIdentifier,
+ IN CONST VOID *Guid OPTIONAL,
+ IN CONST CHAR8 *String OPTIONAL,
+ IN UINT64 Address OPTIONAL,
+ IN UINT32 Identifier
+ )
+{
+ EFI_STATUS Status;
+
+ Status = GetPerformanceMeasurementProtocol ();
+ if (EFI_ERROR (Status)) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ if (mPerformanceMeasurement != NULL) {
+ Status = mPerformanceMeasurement->CreatePerformanceMeasurement (CallerIdentifier, Guid, String, 0, Address, Identifier, PerfEntry);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ return (RETURN_STATUS)Status;
+}
+
+/**
+ Check whether the specified performance measurement can be logged.
+
+ This function returns TRUE when the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set
+ and the Type disable bit in PcdPerformanceLibraryPropertyMask is not set.
+
+ @param Type - Type of the performance measurement entry.
+
+ @retval TRUE The performance measurement can be logged.
+ @retval FALSE The performance measurement can NOT be logged.
+
+**/
+BOOLEAN
+EFIAPI
+LogPerformanceMeasurementEnabled (
+ IN CONST UINTN Type
+ )
+{
+ //
+ // When Performance measurement is enabled and the type is not filtered, the performance can be logged.
+ //
+ if (PerformanceMeasurementEnabled () && ((PcdGet8 (PcdPerformanceLibraryPropertyMask) & Type) == 0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.h b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.h
new file mode 100644
index 0000000..5a26d78
--- /dev/null
+++ b/MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLibInternal.h
@@ -0,0 +1,56 @@
+/** @file
+ Internal library header.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_
+#define SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_
+
+/**
+ Registers a callback to perform library actions needed at exit boot services.
+
+ @param[in] ExitBootServicesProtocolGuid The protocol GUID to register the callback for.
+
+ @retval EFI_SUCCESS The callback was registered successfully.
+ @retval Others An error occurred registering the callback.
+ **/
+EFI_STATUS
+RegisterExitBootServicesCallback (
+ IN CONST EFI_GUID *ExitBootServicesProtocolGuid
+ );
+
+/**
+ Unregisters a callback to perform library actions needed at exit boot services.
+
+ @param[in] ExitBootServicesProtocolGuid The protocol GUID to unregister the callback for.
+
+ @retval EFI_SUCCESS The callback was unregistered successfully.
+ @retval Others An error occurred unregistering the callback.
+ **/
+EFI_STATUS
+UnregisterExitBootServicesCallback (
+ IN CONST EFI_GUID *ExitBootServicesProtocolGuid
+ );
+
+/**
+ This is the Event call back function is triggered in MM to notify the Library
+ the system is entering runtime phase.
+
+ @param[in] Protocol Points to the protocol's unique identifier
+ @param[in] Interface Points to the interface instance
+ @param[in] Handle The handle on which the interface was installed
+
+ @retval EFI_SUCCESS SmmAtRuntimeCallBack runs successfully
+ **/
+EFI_STATUS
+EFIAPI
+SmmPerformanceLibExitBootServicesCallback (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+ );
+
+#endif // SMM_CORE_PERFORMANCE_LIB_INTERNAL_H_
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.c b/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.c
new file mode 100644
index 0000000..4722714
--- /dev/null
+++ b/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.c
@@ -0,0 +1,55 @@
+/** @file
+ Performance Library used in Standalone MM phase.
+
+ This library instance provides infrastructure for Standalone MM drivers to log performance
+ data. It consumes the MM PerformanceEx or Performance Protocol to log performance data. If
+ both MM PerformanceEx and Performance Protocol are not available, it does not log any
+ performance information.
+
+ Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+#include <Guid/EventGroup.h>
+#include "SmmPerformanceLibInternal.h"
+
+/**
+ The constructor function initializes the Performance Measurement Enable flag.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] MmSystemTable A pointer to the MM System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmPerformanceLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ return RegisterExitBootServicesCallback (&gEfiEventExitBootServicesGuid);
+}
+
+/**
+ The destructor function frees resources allocated by constructor.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] MmSystemTable A pointer to the MM System Table.
+
+ @retval EFI_SUCCESS The destructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmPerformanceLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ return UnregisterExitBootServicesCallback (&gEfiEventExitBootServicesGuid);
+}
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.inf b/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.inf
new file mode 100644
index 0000000..b99625f
--- /dev/null
+++ b/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.inf
@@ -0,0 +1,48 @@
+## @file
+# Performance library instance used in Standalone MM phase.
+#
+# This library instance provides infrastructure for Standalone MM drivers to log performance
+# data. It consumes the MM PerformanceEx or Performance Protocol to log performance data. If
+# both MM PerformanceEx and Performance Protocol are not available, it does not log any
+# performance information.
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = StandaloneMmPerformanceLib
+ MODULE_UNI_FILE = StandaloneMmPerformanceLib.uni
+ FILE_GUID = 7E7415FC-0BFB-47B4-B1C8-66149CC9050C
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = PerformanceLib|MM_STANDALONE
+
+ CONSTRUCTOR = StandaloneMmPerformanceLibConstructor
+ DESTRUCTOR = StandaloneMmPerformanceLibDestructor
+
+[Sources]
+ SmmPerformanceLibInternal.h
+ SmmPerformanceLibInternal.c
+ StandaloneMmPerformanceLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ MmServicesTableLib
+ DebugLib
+ BaseMemoryLib
+
+[Guids]
+ gEdkiiSmmPerformanceMeasurementProtocolGuid ## SOMETIMES_CONSUMES ## UNDEFINED # Locate protocol
+ gEfiEventExitBootServicesGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES
diff --git a/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.uni b/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.uni
new file mode 100644
index 0000000..6e6d858
--- /dev/null
+++ b/MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.uni
@@ -0,0 +1,20 @@
+// /** @file
+// Performance library instance used in Standalone MM phase.
+//
+// This library instance provides infrastructure for Standalone MM drivers to log performance
+// data. It consumes the MM PerformanceEx or Performance Protocol to log performance data. If
+// both MM PerformanceEx and Performance Protocol are not available, it does not log any
+// performance information.
+//
+// Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+// Copyright Microsoft Corporation.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Performance library instance used in the Standalone MM phase"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This library instance provides infrastructure for Standalone MM drivers to log performance data. It consumes the Standalone MM PerformanceEx or Performance Protocol to log performance data. If both Standalone MM PerformanceEx and Performance Protocol are not available, it does not log any performance information."
+
diff --git a/MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.c b/MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.c
new file mode 100644
index 0000000..1a29557
--- /dev/null
+++ b/MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.c
@@ -0,0 +1,85 @@
+/** @file
+ NULL instance of TdxMeasurementLib
+ Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <PiPei.h>
+#include <Library/TdxMeasurementLib.h>
+
+/**
+ According to UEFI Spec 2.10 Section 38.4.1:
+ The following table shows the TPM PCR index mapping and CC event log measurement
+ register index interpretation for Intel TDX, where MRTD means Trust Domain Measurement
+ Register and RTMR means Runtime Measurement Register
+ // TPM PCR Index | CC Measurement Register Index | TDX-measurement register
+ // ------------------------------------------------------------------------
+ // 0 | 0 | MRTD
+ // 1, 7 | 1 | RTMR[0]
+ // 2~6 | 2 | RTMR[1]
+ // 8~15 | 3 | RTMR[2]
+ @param[in] PCRIndex Index of the TPM PCR
+ @retval UINT32 Index of the CC Event Log Measurement Register Index
+ @retval CC_MR_INDEX_INVALID Invalid MR Index
+**/
+UINT32
+EFIAPI
+TdxMeasurementMapPcrToMrIndex (
+ IN UINT32 PCRIndex
+ )
+{
+ return CC_MR_INDEX_INVALID;
+}
+
+/**
+ * Calculate the sha384 of input Data and extend it to RTMR register.
+ *
+ * @param RtmrIndex Index of the RTMR register
+ * @param DataToHash Data to be hashed
+ * @param DataToHashLen Length of the data
+ * @param Digest Hash value of the input data
+ * @param DigestLen Length of the hash value
+ *
+ * @retval EFI_SUCCESS Successfully hash and extend to RTMR
+ * @retval Others Other errors as indicated
+ */
+EFI_STATUS
+EFIAPI
+TdxMeasurementHashAndExtendToRtmr (
+ IN UINT32 RtmrIndex,
+ IN VOID *DataToHash,
+ IN UINTN DataToHashLen,
+ OUT UINT8 *Digest,
+ IN UINTN DigestLen
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ * Build GuidHob for Tdx CC measurement event.
+ *
+ * @param RtmrIndex RTMR index
+ * @param EventType Event type
+ * @param EventData Event data
+ * @param EventSize Size of event data
+ * @param HashValue Hash value
+ * @param HashSize Size of hash
+ *
+ * @retval EFI_SUCCESS Successfully build the GuidHobs
+ * @retval Others Other error as indicated
+ */
+EFI_STATUS
+EFIAPI
+TdxMeasurementBuildGuidHob (
+ UINT32 RtmrIndex,
+ UINT32 EventType,
+ UINT8 *EventData,
+ UINT32 EventSize,
+ UINT8 *HashValue,
+ UINT32 HashSize
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.inf b/MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.inf
new file mode 100644
index 0000000..40e6f45
--- /dev/null
+++ b/MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.inf
@@ -0,0 +1,32 @@
+## @file
+# TdxMeasurementLib NULL instance
+#
+# Copyright (c) 2025, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TdxMeasurementNullLib
+ FILE_GUID = 975d11ff-b11e-4cf4-b453-6d93a9ea8d7b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TdxMeasurementLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ TdxMeasurementLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
diff --git a/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.c b/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.c
index 880b428..d6853a1 100644
--- a/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.c
+++ b/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.c
@@ -6,6 +6,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
+#include <Uefi/UefiBaseType.h>
+#include <Library/TpmMeasurementLib.h>
+
/**
Tpm measure and log data, and extend the measurement result into a specific PCR.
diff --git a/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf b/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
index c3be447..96d816b 100644
--- a/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+++ b/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
@@ -10,9 +10,9 @@
INF_VERSION = 0x00010005
BASE_NAME = TpmMeasurementLibNull
FILE_GUID = 6DFD6E9F-9278-48D8-8F45-B6CFF2C2B69C
- MODULE_TYPE = UEFI_DRIVER
+ MODULE_TYPE = BASE
VERSION_STRING = 1.0
- LIBRARY_CLASS = TpmMeasurementLib|SEC PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ LIBRARY_CLASS = TpmMeasurementLib
MODULE_UNI_FILE = TpmMeasurementLibNull.uni
#
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
index 7a97f7c..3343e60 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
@@ -147,6 +147,12 @@ BmFindBootOptionInVariable (
if (OptionNumber == LoadOptionNumberUnassigned) {
BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
+ // Only assert if the BootOption is non-zero
+ if ((BootOptions == NULL) && (BootOptionCount > 0)) {
+ ASSERT (BootOptions != NULL);
+ return LoadOptionNumberUnassigned;
+ }
+
Index = EfiBootManagerFindLoadOption (OptionToFind, BootOptions, BootOptionCount);
if (Index != -1) {
OptionNumber = BootOptions[Index].OptionNumber;
@@ -1535,6 +1541,11 @@ BmExpandLoadFiles (
UINTN HandleCount;
UINTN Index;
EFI_DEVICE_PATH_PROTOCOL *Node;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *HttpPath;
+ URI_DEVICE_PATH *NullUriPath;
+
+ NullUriPath = NULL;
//
// Get file buffer from load file instance.
@@ -1567,11 +1578,50 @@ BmExpandLoadFiles (
for (Index = 0; Index < HandleCount; Index++) {
if (BmMatchHttpBootDevicePath (DevicePathFromHandle (Handles[Index]), FilePath)) {
+ //
+ // Matches HTTP Boot Device Path described as
+ // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)
+ // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)
+ //
+ Handle = Handles[Index];
+ goto Done;
+ }
+ }
+
+ NullUriPath = (URI_DEVICE_PATH *)CreateDeviceNode (
+ MESSAGING_DEVICE_PATH,
+ MSG_URI_DP,
+ (UINT16)(sizeof (URI_DEVICE_PATH))
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ if ((Handles == NULL) || (Handles[Index] == NULL)) {
+ continue;
+ }
+
+ NewDevicePath = DevicePathFromHandle (Handles[Index]);
+ if (NewDevicePath == NULL) {
+ continue;
+ }
+
+ HttpPath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)NullUriPath);
+ if (HttpPath == NULL) {
+ continue;
+ }
+
+ if (BmMatchHttpBootDevicePath (HttpPath, FilePath)) {
+ //
+ // Matches HTTP Boot Device Path described as
+ // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)/Uri(...)
+ // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)/Uri(...)
+ //
Handle = Handles[Index];
break;
}
}
+ FreePool (NullUriPath);
+
+Done:
if (Handles != NULL) {
FreePool (Handles);
}
@@ -2662,3 +2712,80 @@ EfiBootManagerGetNextLoadOptionDevicePath (
{
return BmGetNextLoadOptionDevicePath (FilePath, FullPath);
}
+
+/**
+ Variable policy protocol installation notification.
+
+ @param[in] Event The notification event.
+ @param[in] Context Pointer to the context registered when the event is created. Not used.
+
+**/
+VOID
+EFIAPI
+OnVariablePolicyNotification (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy = NULL;
+
+ Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);
+ if (!EFI_ERROR (Status)) {
+ Status = RegisterBasicVariablePolicy (
+ VariablePolicy,
+ &mBmHardDriveBootVariableGuid,
+ L"HDDP",
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ VARIABLE_POLICY_NO_MAX_SIZE,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ (UINT32) ~(EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE),
+ VARIABLE_POLICY_TYPE_NO_LOCK
+ );
+
+ // Multiple modules link to UefiBootManagerLib. There are a couple of cases that need to be ignored.
+ // 1. Write Protected. Write Protected occurs after Ready to Boot. Some modules, such as the Shell, run
+ // after Ready To Boot.
+ // 2. Already Started. Only the first module to register a variable policy will successfully register
+ // a policy. The subsequent modules will get EFI_ALREADY_STARTED.
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED) && (Status != EFI_WRITE_PROTECTED)) {
+ DEBUG ((DEBUG_ERROR, "%a: - Error setting policy for HDDP - Status=%r\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a: - Unable to locate variable policy protocol - Status=%r\n", __func__, Status));
+ }
+}
+
+/**
+ Constructor for UefiBootMangerLib.
+
+ @param[in] ImageHandle The handle of the loaded image.
+ @param[in] SystemTable System resources and configuration
+
+ @retval EFI_SUCCESS The constructor set the variable policy if implemented
+ @retval others The constructor did not succeed and one or more variable policy are not set
+**/
+EFI_STATUS
+EFIAPI
+UefiBootManagerLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ VOID *Registration;
+
+ EfiCreateProtocolNotifyEvent (
+ &gEdkiiVariablePolicyProtocolGuid,
+ TPL_CALLBACK,
+ OnVariablePolicyNotification,
+ NULL,
+ &Registration
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
index 030b2ee..6106aa5 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmBootDescription.c
@@ -17,6 +17,64 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
CONST UINT16 mBmUsbLangId = 0x0409; // English
CHAR16 mBmUefiPrefix[] = L"UEFI ";
+CHAR16 mBootDescGenericManufacturer[] = L"Generic";
+CHAR16 mBootDescSd[] = L"SD Device";
+CHAR16 mBootDescEmmc[] = L"eMMC Device";
+CHAR16 mBootDescEmmcUserData[] = L"eMMC User Data";
+CHAR16 mBootDescEmmcBoot1[] = L"eMMC Boot 1";
+CHAR16 mBootDescEmmcBoot2[] = L"eMMC Boot 2";
+CHAR16 mBootDescEmmcGp1[] = L"eMMC GP 1";
+CHAR16 mBootDescEmmcGp2[] = L"eMMC GP 2";
+CHAR16 mBootDescEmmcGp3[] = L"eMMC GP 3";
+CHAR16 mBootDescEmmcGp4[] = L"eMMC GP 4";
+
+typedef struct {
+ UINT8 Id;
+ CHAR16 *Name;
+} BM_SDMMC_MANUFACTURER;
+
+BM_SDMMC_MANUFACTURER mSdManufacturers[] = {
+ { 0x01, L"Panasonic" },
+ { 0x02, L"Toshiba/Kingston/Viking" },
+ { 0x03, L"SanDisk" },
+ { 0x08, L"Silicon Power" },
+ { 0x18, L"Infineon" },
+ { 0x1b, L"Transcend/Samsung" },
+ { 0x1c, L"Transcend" },
+ { 0x1d, L"Corsair/AData" },
+ { 0x1e, L"Transcend" },
+ { 0x1f, L"Kingston" },
+ { 0x27, L"Delkin/Phison" },
+ { 0x28, L"Lexar" },
+ { 0x30, L"SanDisk" },
+ { 0x31, L"Silicon Power" },
+ { 0x33, L"STMicroelectronics" },
+ { 0x41, L"Kingston" },
+ { 0x6f, L"STMicroelectronics" },
+ { 0x74, L"Transcend" },
+ { 0x76, L"Patriot" },
+ { 0x82, L"Gobe/Sony" },
+ { 0x9c, L"Angelbird/Hoodman" },
+};
+
+BM_SDMMC_MANUFACTURER mMmcManufacturers[] = {
+ { 0x00, L"SanDisk" },
+ { 0x02, L"Kingston/SanDisk" },
+ { 0x03, L"Toshiba" },
+ { 0x11, L"Toshiba" },
+ { 0x13, L"Micron" },
+ { 0x15, L"Samsung" },
+ { 0x37, L"KingMax" },
+ { 0x44, L"ATP" },
+ { 0x45, L"SanDisk" },
+ { 0x2c, L"Kingston" },
+ { 0x70, L"Kingston" },
+ { 0x88, L"Foresee" },
+ { 0x9b, L"YMTC" },
+ { 0xd6, L"Foresee" },
+ { 0xfe, L"Micron" },
+};
+
LIST_ENTRY mPlatformBootDescriptionHandlers = INITIALIZE_LIST_HEAD_VARIABLE (mPlatformBootDescriptionHandlers);
/**
@@ -128,6 +186,150 @@ BmEliminateExtraSpaces (
}
/**
+ Swap a byte array.
+
+ @param Source Input byte array.
+ @param Length The size of Source in bytes.
+**/
+VOID
+BmSwapBytes (
+ IN UINT8 *Source,
+ IN UINTN Length
+ )
+{
+ UINTN Index;
+ UINT8 Temp;
+ UINTN Count;
+
+ Count = Length / 2;
+ for (Index = 0; Index < Count; ++Index) {
+ Temp = Source[Index];
+ Source[Index] = Source[Length - 1 - Index];
+ Source[Length - 1 - Index] = Temp;
+ }
+}
+
+/**
+ Get the SD/MMC manufacturer name from an ID.
+
+ @param Id Manufacturer ID.
+ @param IsMmc Boolean indicating whether the ID is for SD or eMMC.
+
+ @return The manufacturer string.
+**/
+CHAR16 *
+BmGetSdMmcManufacturerName (
+ IN UINT8 Id,
+ IN BOOLEAN IsMmc
+ )
+{
+ BM_SDMMC_MANUFACTURER *List;
+ UINT8 Count;
+ UINTN Index;
+
+ List = IsMmc ? mMmcManufacturers : mSdManufacturers;
+ Count = IsMmc ? ARRAY_SIZE (mMmcManufacturers)
+ : ARRAY_SIZE (mSdManufacturers);
+
+ for (Index = 0; Index < Count; ++Index) {
+ if (List[Index].Id == Id) {
+ return List[Index].Name;
+ }
+ }
+
+ return mBootDescGenericManufacturer;
+}
+
+/**
+ Get the eMMC partition type from a controller path.
+
+ @param DevicePath Pointer to a CONTROLLER_DEVICE_PATH.
+
+ @return The description string.
+**/
+CHAR16 *
+BmGetEmmcTypeDescription (
+ CONTROLLER_DEVICE_PATH *DevicePath
+ )
+{
+ switch (DevicePath->ControllerNumber) {
+ case EmmcPartitionUserData:
+ return mBootDescEmmcUserData;
+ case EmmcPartitionBoot1:
+ return mBootDescEmmcBoot1;
+ case EmmcPartitionBoot2:
+ return mBootDescEmmcBoot2;
+ case EmmcPartitionGP1:
+ return mBootDescEmmcGp1;
+ case EmmcPartitionGP2:
+ return mBootDescEmmcGp2;
+ case EmmcPartitionGP3:
+ return mBootDescEmmcGp3;
+ case EmmcPartitionGP4:
+ return mBootDescEmmcGp4;
+ default:
+ break;
+ }
+
+ return mBootDescEmmc;
+}
+
+/**
+ Get an SD/MMC boot description.
+
+ @param ManufacturerName Manufacturer name string.
+ @param ProductName Product name from CID.
+ @param ProductNameLength Length of ProductName.
+ @param SerialNumber Serial number from CID.
+ @param DeviceType Device type string (e.g. SD or an eMMC partition).
+
+ @return The description string.
+**/
+CHAR16 *
+BmGetSdMmcDescription (
+ IN CHAR16 *ManufacturerName,
+ IN UINT8 *ProductName,
+ IN UINT8 ProductNameLength,
+ IN UINT8 SerialNumber[4],
+ IN CHAR16 *DeviceType
+ )
+{
+ CHAR16 *Desc;
+ UINTN DescSize;
+
+ DescSize = StrSize (ManufacturerName) - sizeof (CHAR16) // "Samsung"
+ + sizeof (CHAR16) // " "
+ + ProductNameLength * sizeof (CHAR16) // "BJTD4R"
+ + sizeof (CHAR16) // " "
+ + sizeof (UINT32) * 2 * sizeof (CHAR16) // "00000000"
+ + sizeof (CHAR16) // " "
+ + StrSize (DeviceType); // "eMMC User Data\0"
+
+ Desc = AllocateZeroPool (DescSize);
+ if (Desc == NULL) {
+ return NULL;
+ }
+
+ BmSwapBytes (ProductName, ProductNameLength);
+
+ UnicodeSPrint (
+ Desc,
+ DescSize,
+ L"%s %.*a %02x%02x%02x%02x %s",
+ ManufacturerName,
+ ProductNameLength,
+ ProductName,
+ SerialNumber[0],
+ SerialNumber[1],
+ SerialNumber[2],
+ SerialNumber[3],
+ DeviceType
+ );
+
+ return Desc;
+}
+
+/**
Try to get the controller's ATA/ATAPI description.
@param Handle Controller handle.
@@ -145,6 +347,8 @@ BmGetDescriptionFromDiskInfo (
UINT32 BufferSize;
EFI_ATAPI_IDENTIFY_DATA IdentifyData;
EFI_SCSI_INQUIRY_DATA InquiryData;
+ SD_CID SdCid;
+ EMMC_CID EmmcCid;
CHAR16 *Description;
UINTN Length;
CONST UINTN ModelNameLength = 40;
@@ -245,9 +449,40 @@ BmGetDescriptionFromDiskInfo (
}
if (DevicePathSubType (DevicePath) == MSG_SD_DP) {
- Description = L"SD Device";
+ BufferSize = sizeof (SD_CID);
+ Status = DiskInfo->Inquiry (DiskInfo, &SdCid, &BufferSize);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Description = BmGetSdMmcDescription (
+ BmGetSdMmcManufacturerName (SdCid.ManufacturerId, FALSE),
+ SdCid.ProductName,
+ ARRAY_SIZE (SdCid.ProductName),
+ SdCid.ProductSerialNumber,
+ mBootDescSd
+ );
} else if (DevicePathSubType (DevicePath) == MSG_EMMC_DP) {
- Description = L"eMMC Device";
+ BufferSize = sizeof (EMMC_CID);
+ Status = DiskInfo->Inquiry (DiskInfo, &EmmcCid, &BufferSize);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Description = mBootDescEmmc;
+
+ DevicePath = NextDevicePathNode (DevicePath);
+ if (DevicePath->SubType == HW_CONTROLLER_DP) {
+ Description = BmGetEmmcTypeDescription ((CONTROLLER_DEVICE_PATH *)DevicePath);
+ }
+
+ Description = BmGetSdMmcDescription (
+ BmGetSdMmcManufacturerName (EmmcCid.ManufacturerId, TRUE),
+ EmmcCid.ProductName,
+ ARRAY_SIZE (EmmcCid.ProductName),
+ EmmcCid.ProductSerialNumber,
+ Description
+ );
} else {
return NULL;
}
@@ -414,8 +649,8 @@ BmGetNetworkDescription (
// ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)
//
// The HTTP device path is like:
- // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]/Uri(...)
- // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(...)
+ // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)][/Uri(...)]/Uri(...)
+ // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)][/Uri(...)]/Uri(...)
//
while (!IsDevicePathEnd (DevicePath) &&
((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c b/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
index 46a8b78..1f6786f 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmDriverHealth.c
@@ -105,6 +105,79 @@ BmGetControllerName (
}
/**
+ Return the driver name.
+
+ @param DriverHealthHandle The handle on which the Driver Health protocol instance is retrieved.
+
+ @return A pointer to the Unicode string to return. This Unicode string is the name of the controller
+ specified by DriverHealthHandle.
+**/
+CHAR16 *
+BmGetDriverName (
+ IN EFI_HANDLE DriverHealthHandle
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *DriverName;
+ CHAR8 *LanguageVariable;
+ CHAR8 *BestLanguage;
+ BOOLEAN Iso639Language;
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
+
+ DriverName = NULL;
+
+ //
+ // Locate Component Name (2) protocol on the driver binging handle.
+ //
+ Iso639Language = FALSE;
+ Status = gBS->HandleProtocol (
+ DriverHealthHandle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID **)&ComponentName
+ );
+ if (EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (
+ DriverHealthHandle,
+ &gEfiComponentNameProtocolGuid,
+ (VOID **)&ComponentName
+ );
+ if (!EFI_ERROR (Status)) {
+ Iso639Language = TRUE;
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ GetEfiGlobalVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", (VOID **)&LanguageVariable, NULL);
+ BestLanguage = GetBestLanguage (
+ ComponentName->SupportedLanguages,
+ Iso639Language,
+ (LanguageVariable != NULL) ? LanguageVariable : "",
+ Iso639Language ? "eng" : "en-US",
+ NULL
+ );
+ if (LanguageVariable != NULL) {
+ FreePool (LanguageVariable);
+ }
+
+ Status = ComponentName->GetDriverName (
+ ComponentName,
+ BestLanguage,
+ &DriverName
+ );
+ }
+
+ if (!EFI_ERROR (Status)) {
+ return AllocateCopyPool (StrSize (DriverName), DriverName);
+ } else {
+ return ConvertDevicePathToText (
+ DevicePathFromHandle (DriverHealthHandle),
+ FALSE,
+ FALSE
+ );
+ }
+}
+
+/**
Display a set of messages returned by the GetHealthStatus () service of the EFI Driver Health Protocol
@param DriverHealthInfo Pointer to the Driver Health information entry.
@@ -116,7 +189,8 @@ BmDisplayMessages (
{
UINTN Index;
EFI_STRING String;
- CHAR16 *ControllerName;
+ CHAR16 *ControllerName = NULL;
+ CHAR16 *DriverName = NULL;
if ((DriverHealthInfo->MessageList == NULL) ||
(DriverHealthInfo->MessageList[0].HiiHandle == NULL))
@@ -124,14 +198,30 @@ BmDisplayMessages (
return;
}
- ControllerName = BmGetControllerName (
- DriverHealthInfo->DriverHealthHandle,
- DriverHealthInfo->ControllerHandle,
- DriverHealthInfo->ChildHandle
- );
+ if (DriverHealthInfo->DriverHealthHandle != NULL) {
+ DriverName = BmGetDriverName (DriverHealthInfo->DriverHealthHandle);
+ if (DriverName != NULL) {
+ DEBUG ((DEBUG_INFO, "Driver: %s\n", DriverName));
+ Print (L"Driver: %s\n", DriverName);
+ }
+ }
+
+ if (DriverHealthInfo->ControllerHandle != NULL) {
+ ControllerName = BmGetControllerName (
+ DriverHealthInfo->DriverHealthHandle,
+ DriverHealthInfo->ControllerHandle,
+ DriverHealthInfo->ChildHandle
+ );
+ if (ControllerName != NULL) {
+ DEBUG ((DEBUG_INFO, "Controller: %s\n", ControllerName));
+ Print (L"Controller: %s\n", ControllerName);
+ }
+ }
+
+ if ((DriverName == NULL) && (ControllerName == NULL)) {
+ return;
+ }
- DEBUG ((DEBUG_INFO, "Controller: %s\n", ControllerName));
- Print (L"Controller: %s\n", ControllerName);
for (Index = 0; DriverHealthInfo->MessageList[Index].HiiHandle != NULL; Index++) {
String = HiiGetString (
DriverHealthInfo->MessageList[Index].HiiHandle,
@@ -147,6 +237,12 @@ BmDisplayMessages (
if (ControllerName != NULL) {
FreePool (ControllerName);
+ ControllerName = NULL;
+ }
+
+ if (DriverName != NULL) {
+ FreePool (DriverName);
+ DriverName = NULL;
}
}
@@ -550,24 +646,58 @@ BmRepairAllControllers (
EfiBootManagerFreeDriverHealthInfo (DriverHealthInfo, Count);
DEBUG_CODE_BEGIN ();
- CHAR16 *ControllerName;
+ CHAR16 *ControllerName = NULL;
+ CHAR16 *DriverName = NULL;
+ CHAR16 String[512];
DriverHealthInfo = EfiBootManagerGetDriverHealthInfo (&Count);
for (Index = 0; Index < Count; Index++) {
- ControllerName = BmGetControllerName (
- DriverHealthInfo[Index].DriverHealthHandle,
- DriverHealthInfo[Index].ControllerHandle,
- DriverHealthInfo[Index].ChildHandle
- );
+ if (DriverHealthInfo == NULL) {
+ continue;
+ }
+
+ ZeroMem (String, sizeof (String));
+ if (DriverHealthInfo[Index].DriverHealthHandle != NULL) {
+ DriverName = BmGetDriverName (DriverHealthInfo[Index].DriverHealthHandle);
+ }
+
+ if (DriverHealthInfo[Index].ControllerHandle != NULL) {
+ ControllerName = BmGetControllerName (
+ DriverHealthInfo[Index].DriverHealthHandle,
+ DriverHealthInfo[Index].ControllerHandle,
+ DriverHealthInfo[Index].ChildHandle
+ );
+ }
+
+ if ((DriverName == NULL) && (ControllerName == NULL)) {
+ continue;
+ }
+
+ UnicodeSPrint (
+ String,
+ sizeof (String),
+ L"%s%s%s",
+ DriverName != NULL ? DriverName : L"",
+ (DriverName != NULL && ControllerName != NULL) ? L" " : L"",
+ ControllerName != NULL ? ControllerName : L""
+ );
+
DEBUG ((
DEBUG_INFO,
"%02d: %s - %s\n",
Index,
- ControllerName,
+ String,
mBmHealthStatusText[DriverHealthInfo[Index].HealthStatus]
));
+
if (ControllerName != NULL) {
FreePool (ControllerName);
+ ControllerName = NULL;
+ }
+
+ if (DriverName != NULL) {
+ FreePool (DriverName);
+ DriverName = NULL;
}
}
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
index 83a2f89..7813c87 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
+++ b/MdeModulePkg/Library/UefiBootManagerLib/BmLoadOption.c
@@ -9,8 +9,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "InternalBm.h"
-#include <Library/VariablePolicyHelperLib.h>
-
GLOBAL_REMOVE_IF_UNREFERENCED
CHAR16 *mBmLoadOptionName[] = {
L"Driver",
@@ -439,6 +437,10 @@ EfiBootManagerSortLoadOptionVariable (
LoadOption = EfiBootManagerGetLoadOptions (&LoadOptionCount, OptionType);
+ if (LoadOptionCount == 0) {
+ return;
+ }
+
//
// Insertion sort algorithm
//
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
index b7dfe2a..a4ff491 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
+++ b/MdeModulePkg/Library/UefiBootManagerLib/InternalBm.h
@@ -18,6 +18,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <IndustryStandard/Atapi.h>
#include <IndustryStandard/Scsi.h>
#include <IndustryStandard/Nvme.h>
+#include <IndustryStandard/Sd.h>
+#include <IndustryStandard/Emmc.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/BlockIo.h>
@@ -42,6 +44,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/RamDisk.h>
#include <Protocol/DeferredImageLoad.h>
#include <Protocol/PlatformBootManager.h>
+#include <Protocol/VariablePolicy.h>
#include <Guid/MemoryTypeInformation.h>
#include <Guid/FileInfo.h>
@@ -69,6 +72,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/CapsuleLib.h>
#include <Library/PerformanceLib.h>
#include <Library/HiiLib.h>
+#include <Library/VariablePolicyHelperLib.h>
#if !defined (EFI_REMOVABLE_MEDIA_FILE_NAME)
#if defined (MDE_CPU_EBC)
diff --git a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
index 2fc0a80..4007262 100644
--- a/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+++ b/MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
@@ -101,7 +101,7 @@
gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES
gEfiBootLogoProtocolGuid ## SOMETIMES_CONSUMES
gEfiSimpleTextInputExProtocolGuid ## SOMETIMES_CONSUMES
- gEdkiiVariablePolicyProtocolGuid ## SOMETIMES_CONSUMES
+ gEdkiiVariablePolicyProtocolGuid ## SOMETIMES_CONSUMES ## NOTIFY
gEfiGraphicsOutputProtocolGuid ## SOMETIMES_CONSUMES
gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
gEfiNvmExpressPassThruProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h
index 89de54d..59b51e8 100644
--- a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHii.h
@@ -1,7 +1,7 @@
/** @file
Include file for Var Check Hii handler and bin.
-Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -51,7 +51,11 @@ DumpVarCheckHii (
IN UINTN VarCheckHiiBinSize
);
-extern VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin;
-extern UINTN mVarCheckHiiBinSize;
+#define VAR_CHECK_RECEIVED_HII_BIN_HANDLER_GUID \
+ { \
+ 0xe63095c7, 0x2b34, 0x4163, { 0x80, 0x3d, 0xc8, 0x3c, 0x2e, 0xd6, 0xa0, 0x37 } \
+ }
+
+extern EFI_GUID gVarCheckReceivedHiiBinHandlerGuid;
#endif
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c
index ca8227d..abc5fd4 100644
--- a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.c
@@ -1,14 +1,17 @@
/** @file
Var Check Hii bin generation.
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "VarCheckHiiGen.h"
+#include "VarCheckHii.h"
-LIST_ENTRY mVarCheckHiiList = INITIALIZE_LIST_HEAD_VARIABLE (mVarCheckHiiList);
+VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin = NULL;
+UINTN mVarCheckHiiBinSize = 0;
+LIST_ENTRY mVarCheckHiiList = INITIALIZE_LIST_HEAD_VARIABLE (mVarCheckHiiList);
#define VAR_CHECK_HII_VARIABLE_NODE_SIGNATURE SIGNATURE_32 ('V', 'C', 'H', 'V')
@@ -1511,7 +1514,7 @@ DestroyHiiVariableNode (
**/
VOID *
BuildVarCheckHiiBin (
- OUT UINTN *Size
+ IN OUT UINTN *Size
)
{
VAR_CHECK_HII_VARIABLE_NODE *HiiVariableNode;
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h
index c70bf72..ace1fe6 100644
--- a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGen.h
@@ -1,7 +1,7 @@
/** @file
Include file for Var Check Hii bin generation.
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -10,6 +10,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define _VAR_CHECK_HII_GEN_H_
#include "VarCheckHii.h"
+extern VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin;
+extern UINTN mVarCheckHiiBinSize;
/**
Dump Hii Package.
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c
index 27d10f8..6f152d4 100644
--- a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiGenFromHii.c
@@ -65,3 +65,254 @@ VarCheckHiiGenFromHiiDatabase (
gBS->FreePages (BufferAddress, EFI_SIZE_TO_PAGES (BufferSize));
}
}
+
+#ifdef DUMP_VAR_CHECK_HII
+GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mHiiOpCodeStringTable[] = {
+ { EFI_IFR_VARSTORE_EFI_OP, "EfiVarStore" },
+ { EFI_IFR_ONE_OF_OP, "OneOf" },
+ { EFI_IFR_CHECKBOX_OP, "CheckBox" },
+ { EFI_IFR_NUMERIC_OP, "Numeric" },
+ { EFI_IFR_ORDERED_LIST_OP, "OrderedList" },
+};
+
+/**
+ HII opcode to string.
+
+ @param[in] HiiOpCode Hii OpCode.
+
+ @return Pointer to string.
+
+**/
+CHAR8 *
+HiiOpCodeToStr (
+ IN UINT8 HiiOpCode
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < ARRAY_SIZE (mHiiOpCodeStringTable); Index++) {
+ if (mHiiOpCodeStringTable[Index].HiiOpCode == HiiOpCode) {
+ return mHiiOpCodeStringTable[Index].HiiOpCodeStr;
+ }
+ }
+
+ return "<UnknownHiiOpCode>";
+}
+
+/**
+ Dump Hii Question.
+
+ @param[in] HiiQuestion Pointer to Hii Question.
+
+**/
+VOID
+DumpHiiQuestion (
+ IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion
+ )
+{
+ UINT64 Minimum;
+ UINT64 Maximum;
+ UINT64 OneValue;
+ UINT8 *Ptr;
+
+ DEBUG ((DEBUG_INFO, " VAR_CHECK_HII_QUESTION_HEADER\n"));
+ DEBUG ((DEBUG_INFO, " OpCode - 0x%02x (%a) (%a)\n", HiiQuestion->OpCode, HiiOpCodeToStr (HiiQuestion->OpCode), (HiiQuestion->BitFieldStore ? "bit level" : "byte level")));
+ DEBUG ((DEBUG_INFO, " Length - 0x%02x\n", HiiQuestion->Length));
+ DEBUG ((DEBUG_INFO, " VarOffset - 0x%04x (%a)\n", HiiQuestion->VarOffset, (HiiQuestion->BitFieldStore ? "bit level" : "byte level")));
+ DEBUG ((DEBUG_INFO, " StorageWidth - 0x%02x (%a)\n", HiiQuestion->StorageWidth, (HiiQuestion->BitFieldStore ? "bit level" : "byte level")));
+
+ switch (HiiQuestion->OpCode) {
+ case EFI_IFR_ONE_OF_OP:
+ Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ONEOF *)HiiQuestion + 1);
+ while ((UINTN)Ptr < ((UINTN)HiiQuestion + HiiQuestion->Length)) {
+ OneValue = 0;
+ if (HiiQuestion->BitFieldStore) {
+ //
+ // For OneOf stored in bit field, the value of options are saved as UINT32 type.
+ //
+ CopyMem (&OneValue, Ptr, sizeof (UINT32));
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%08x\n", OneValue));
+ } else {
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
+ switch (HiiQuestion->StorageWidth) {
+ case sizeof (UINT8):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%02x\n", OneValue));
+ break;
+ case sizeof (UINT16):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%04x\n", OneValue));
+ break;
+ case sizeof (UINT32):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%08x\n", OneValue));
+ break;
+ case sizeof (UINT64):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%016lx\n", OneValue));
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ }
+
+ if (HiiQuestion->BitFieldStore) {
+ Ptr += sizeof (UINT32);
+ } else {
+ Ptr += HiiQuestion->StorageWidth;
+ }
+ }
+
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ Minimum = 0;
+ Maximum = 0;
+ Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_NUMERIC *)HiiQuestion + 1);
+ if (HiiQuestion->BitFieldStore) {
+ //
+ // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
+ //
+ CopyMem (&Minimum, Ptr, sizeof (UINT32));
+ Ptr += sizeof (UINT32);
+ CopyMem (&Maximum, Ptr, sizeof (UINT32));
+ Ptr += sizeof (UINT32);
+
+ DEBUG ((DEBUG_INFO, " Minimum - 0x%08x\n", Minimum));
+ DEBUG ((DEBUG_INFO, " Maximum - 0x%08x\n", Maximum));
+ } else {
+ CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);
+ Ptr += HiiQuestion->StorageWidth;
+ CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);
+ Ptr += HiiQuestion->StorageWidth;
+
+ switch (HiiQuestion->StorageWidth) {
+ case sizeof (UINT8):
+ DEBUG ((DEBUG_INFO, " Minimum - 0x%02x\n", Minimum));
+ DEBUG ((DEBUG_INFO, " Maximum - 0x%02x\n", Maximum));
+ break;
+ case sizeof (UINT16):
+ DEBUG ((DEBUG_INFO, " Minimum - 0x%04x\n", Minimum));
+ DEBUG ((DEBUG_INFO, " Maximum - 0x%04x\n", Maximum));
+ break;
+ case sizeof (UINT32):
+ DEBUG ((DEBUG_INFO, " Minimum - 0x%08x\n", Minimum));
+ DEBUG ((DEBUG_INFO, " Maximum - 0x%08x\n", Maximum));
+ break;
+ case sizeof (UINT64):
+ DEBUG ((DEBUG_INFO, " Minimum - 0x%016lx\n", Minimum));
+ DEBUG ((DEBUG_INFO, " Maximum - 0x%016lx\n", Maximum));
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ }
+
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ DEBUG ((DEBUG_INFO, " MaxContainers - 0x%02x\n", ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion)->MaxContainers));
+ Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion + 1);
+ while ((UINTN)Ptr < ((UINTN)HiiQuestion + HiiQuestion->Length)) {
+ OneValue = 0;
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
+ switch (HiiQuestion->StorageWidth) {
+ case sizeof (UINT8):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%02x\n", OneValue));
+ break;
+ case sizeof (UINT16):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%04x\n", OneValue));
+ break;
+ case sizeof (UINT32):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%08x\n", OneValue));
+ break;
+ case sizeof (UINT64):
+ DEBUG ((DEBUG_INFO, " OneOfOption - 0x%016lx\n", OneValue));
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ Ptr += HiiQuestion->StorageWidth;
+ }
+
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+}
+
+/**
+ Dump Hii Variable.
+
+ @param[in] HiiVariable Pointer to Hii Variable.
+
+**/
+VOID
+DumpHiiVariable (
+ IN VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable
+ )
+{
+ VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;
+
+ DEBUG ((DEBUG_INFO, "VAR_CHECK_HII_VARIABLE_HEADER\n"));
+ DEBUG ((DEBUG_INFO, " Revision - 0x%04x\n", HiiVariable->Revision));
+ DEBUG ((DEBUG_INFO, " HeaderLength - 0x%04x\n", HiiVariable->HeaderLength));
+ DEBUG ((DEBUG_INFO, " Length - 0x%08x\n", HiiVariable->Length));
+ DEBUG ((DEBUG_INFO, " OpCode - 0x%02x (%a)\n", HiiVariable->OpCode, HiiOpCodeToStr (HiiVariable->OpCode)));
+ DEBUG ((DEBUG_INFO, " Size - 0x%04x\n", HiiVariable->Size));
+ DEBUG ((DEBUG_INFO, " Attributes - 0x%08x\n", HiiVariable->Attributes));
+ DEBUG ((DEBUG_INFO, " Guid - %g\n", &HiiVariable->Guid));
+ DEBUG ((DEBUG_INFO, " Name - %s\n", HiiVariable + 1));
+
+ //
+ // For Hii Question header align.
+ //
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->HeaderLength));
+ while ((UINTN)HiiQuestion < ((UINTN)HiiVariable + HiiVariable->Length)) {
+ //
+ // Dump Hii Question related to the Hii Variable.
+ //
+ DumpHiiQuestion (HiiQuestion);
+ //
+ // For Hii Question header align.
+ //
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiQuestion + HiiQuestion->Length));
+ }
+}
+
+/**
+ Dump Var Check HII.
+
+ @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.
+ @param[in] VarCheckHiiBinSize VarCheckHiiBin size.
+
+**/
+VOID
+DumpVarCheckHii (
+ IN VOID *VarCheckHiiBin,
+ IN UINTN VarCheckHiiBinSize
+ )
+{
+ VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
+
+ DEBUG ((DEBUG_INFO, "DumpVarCheckHii\n"));
+
+ //
+ // For Hii Variable header align.
+ //
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (VarCheckHiiBin);
+ while ((UINTN)HiiVariable < ((UINTN)VarCheckHiiBin + VarCheckHiiBinSize)) {
+ DumpHiiVariable (HiiVariable);
+ //
+ // For Hii Variable header align.
+ //
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->Length));
+ }
+}
+
+#endif
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.c
new file mode 100644
index 0000000..22b2755
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.c
@@ -0,0 +1,57 @@
+/** @file
+ Var Check Hii handler.
+
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "VarCheckHii.h"
+#include "VarCheckHiiGen.h"
+#include "VarCheckHiiLibCommon.h"
+
+/**
+ Sets the variable check handler for HII.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] Attributes Attribute value of the variable.
+ @param[in] DataSize Size of Data to set.
+ @param[in] Data Data pointer.
+ @retval EFI_SUCCESS The SetVariable check result was success.
+ @retval EFI_SECURITY_VIOLATION Check fail.
+**/
+EFI_STATUS
+EFIAPI
+SetVariableCheckHandlerHii (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ return CheckHiiVariableCommon (mVarCheckHiiBin, mVarCheckHiiBinSize, VariableName, VendorGuid, Attributes, DataSize, Data);
+}
+
+/**
+ Constructor function of VarCheckHiiLib to register var check HII handler.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor executed correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckHiiLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen);
+ VarCheckLibRegisterAddressPointer ((VOID **)&mVarCheckHiiBin);
+ VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii);
+
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
index 9e55d20..f25b190 100644
--- a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
@@ -1,5 +1,5 @@
## @file
-# NULL class library to register var check HII handler.
+# VarCheckHiiLib library to register var check HII handler.
#
# Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
#
@@ -15,16 +15,18 @@
MODULE_TYPE = DXE_RUNTIME_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
- CONSTRUCTOR = VarCheckHiiLibNullClassConstructor
+ CONSTRUCTOR = VarCheckHiiLibConstructor
[Sources]
- VarCheckHiiLibNullClass.c
+ VarCheckHiiLib.c
VarCheckHii.h
VarCheckHiiGenFromFv.c
VarCheckHiiGenFromHii.c
VarCheckHiiGen.c
VarCheckHiiGen.h
InternalVarCheckStructure.h
+ VarCheckHiiLibCommon.c
+ VarCheckHiiLibCommon.h
[Packages]
MdePkg/MdePkg.dec
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.c
new file mode 100644
index 0000000..00a37df
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.c
@@ -0,0 +1,349 @@
+/** @file
+ Var Check Hii Lib Common logic
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+
+#include "VarCheckHii.h"
+#include "VarCheckHiiLibCommon.h"
+EFI_HANDLE mEfiVariableCheckHiiHandle = NULL;
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckHiiHex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+/**
+ Dump some hexadecimal data.
+ @param[in] Indent How many spaces to indent the output.
+ @param[in] Offset The offset of the dump.
+ @param[in] DataSize The size in bytes of UserData.
+ @param[in] UserData The data to dump.
+**/
+VOID
+VarCheckHiiInternalDumpHex (
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ )
+{
+ UINT8 *Data;
+
+ CHAR8 Val[50];
+
+ CHAR8 Str[20];
+
+ UINT8 TempByte;
+ UINTN Size;
+ UINTN Index;
+
+ Data = UserData;
+ while (DataSize != 0) {
+ Size = 16;
+ if (Size > DataSize) {
+ Size = DataSize;
+ }
+
+ for (Index = 0; Index < Size; Index += 1) {
+ TempByte = Data[Index];
+ Val[Index * 3 + 0] = mVarCheckHiiHex[TempByte >> 4];
+ Val[Index * 3 + 1] = mVarCheckHiiHex[TempByte & 0xF];
+ Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
+ Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
+ }
+
+ Val[Index * 3] = 0;
+ Str[Index] = 0;
+ DEBUG ((DEBUG_INFO, "%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str));
+
+ Data += Size;
+ Offset += Size;
+ DataSize -= Size;
+ }
+}
+
+/**
+ Var Check Hii Question.
+ @param[in] HiiQuestion Pointer to Hii Question
+ @param[in] Data Data pointer.
+ @param[in] DataSize Size of Data to set.
+ @retval TRUE Check pass
+ @retval FALSE Check fail.
+**/
+BOOLEAN
+VarCheckHiiQuestion (
+ IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion,
+ IN VOID *Data,
+ IN UINTN DataSize
+ )
+{
+ UINT64 OneData;
+ UINT64 Minimum;
+ UINT64 Maximum;
+ UINT64 OneValue;
+ UINT8 *Ptr;
+ UINT8 Index;
+ UINT8 MaxContainers;
+ UINT8 StartBit;
+ UINT8 EndBit;
+ UINT8 TotalBits;
+ UINT16 VarOffsetByteLevel;
+ UINT8 StorageWidthByteLevel;
+
+ if (HiiQuestion->BitFieldStore) {
+ VarOffsetByteLevel = HiiQuestion->VarOffset / 8;
+ TotalBits = HiiQuestion->VarOffset % 8 + HiiQuestion->StorageWidth;
+ StorageWidthByteLevel = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);
+ } else {
+ VarOffsetByteLevel = HiiQuestion->VarOffset;
+ StorageWidthByteLevel = HiiQuestion->StorageWidth;
+ }
+
+ if (((UINT32)VarOffsetByteLevel + StorageWidthByteLevel) > DataSize) {
+ DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x)) > Size(0x%x)\n", VarOffsetByteLevel, StorageWidthByteLevel, DataSize));
+ return FALSE;
+ }
+
+ OneData = 0;
+ CopyMem (&OneData, (UINT8 *)Data + VarOffsetByteLevel, StorageWidthByteLevel);
+ if (HiiQuestion->BitFieldStore) {
+ //
+ // Get the value from the bit field.
+ //
+ StartBit = HiiQuestion->VarOffset % 8;
+ EndBit = StartBit + HiiQuestion->StorageWidth - 1;
+ OneData = BitFieldRead64 (OneData, StartBit, EndBit);
+ }
+
+ switch (HiiQuestion->OpCode) {
+ case EFI_IFR_ONE_OF_OP:
+ Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ONEOF *)HiiQuestion + 1);
+ while ((UINTN)Ptr < (UINTN)HiiQuestion + HiiQuestion->Length) {
+ OneValue = 0;
+ if (HiiQuestion->BitFieldStore) {
+ //
+ // For OneOf stored in bit field, the value of options are saved as UINT32 type.
+ //
+ CopyMem (&OneValue, Ptr, sizeof (UINT32));
+ } else {
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
+ }
+
+ if (OneData == OneValue) {
+ //
+ // Match
+ //
+ break;
+ }
+
+ if (HiiQuestion->BitFieldStore) {
+ Ptr += sizeof (UINT32);
+ } else {
+ Ptr += HiiQuestion->StorageWidth;
+ }
+ }
+
+ if ((UINTN)Ptr >= ((UINTN)HiiQuestion + HiiQuestion->Length)) {
+ //
+ // No match
+ //
+ DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData));
+ DEBUG_CODE (
+ VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
+ );
+ return FALSE;
+ }
+
+ break;
+
+ case EFI_IFR_CHECKBOX_OP:
+ if ((OneData != 0) && (OneData != 1)) {
+ DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: CheckBox mismatch (0x%lx)\n", OneData));
+ DEBUG_CODE (
+ VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
+ );
+ return FALSE;
+ }
+
+ break;
+
+ case EFI_IFR_NUMERIC_OP:
+ Minimum = 0;
+ Maximum = 0;
+ Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_NUMERIC *)HiiQuestion + 1);
+ if (HiiQuestion->BitFieldStore) {
+ //
+ // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
+ //
+ CopyMem (&Minimum, Ptr, sizeof (UINT32));
+ Ptr += sizeof (UINT32);
+ CopyMem (&Maximum, Ptr, sizeof (UINT32));
+ Ptr += sizeof (UINT32);
+ } else {
+ CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);
+ Ptr += HiiQuestion->StorageWidth;
+ CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);
+ Ptr += HiiQuestion->StorageWidth;
+ }
+
+ //
+ // No need to check Step, because it is ONLY for UI.
+ //
+ if ((OneData < Minimum) || (OneData > Maximum)) {
+ DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: Numeric mismatch (0x%lx)\n", OneData));
+ DEBUG_CODE (
+ VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
+ );
+ return FALSE;
+ }
+
+ break;
+
+ case EFI_IFR_ORDERED_LIST_OP:
+ MaxContainers = ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion)->MaxContainers;
+ if (((UINT32)HiiQuestion->VarOffset + HiiQuestion->StorageWidth * MaxContainers) > DataSize) {
+ DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x) * MaxContainers(0x%02x)) > Size(0x%x)\n", HiiQuestion->VarOffset, HiiQuestion->StorageWidth, MaxContainers, DataSize));
+ return FALSE;
+ }
+
+ for (Index = 0; Index < MaxContainers; Index++) {
+ OneData = 0;
+ CopyMem (&OneData, (UINT8 *)Data + HiiQuestion->VarOffset + HiiQuestion->StorageWidth * Index, HiiQuestion->StorageWidth);
+ if (OneData == 0) {
+ //
+ // The value of 0 is used to determine if a particular "slot" in the array is empty.
+ //
+ continue;
+ }
+
+ Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion + 1);
+ while ((UINTN)Ptr < ((UINTN)HiiQuestion + HiiQuestion->Length)) {
+ OneValue = 0;
+ CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
+ if (OneData == OneValue) {
+ //
+ // Match
+ //
+ break;
+ }
+
+ Ptr += HiiQuestion->StorageWidth;
+ }
+
+ if ((UINTN)Ptr >= ((UINTN)HiiQuestion + HiiQuestion->Length)) {
+ //
+ // No match
+ //
+ DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: OrderedList mismatch\n"));
+ DEBUG_CODE (
+ VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->StorageWidth * MaxContainers, (UINT8 *)Data + HiiQuestion->VarOffset);
+ );
+ DEBUG_CODE (
+ VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
+ );
+ return FALSE;
+ }
+ }
+
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ return TRUE;
+}
+
+/**
+ SetVariable check handler HII.
+ @param[in] HiiVariableBin Variable BIN.
+ @param[in] HiiVariableBinSize The size of Variable BIN.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] Attributes Attribute value of the variable.
+ @param[in] DataSize Size of Data to set.
+ @param[in] Data Data pointer.
+ @retval EFI_SUCCESS The SetVariable check result was success.
+ @retval EFI_SECURITY_VIOLATION Check fail.
+**/
+EFI_STATUS
+EFIAPI
+CheckHiiVariableCommon (
+ IN VAR_CHECK_HII_VARIABLE_HEADER *HiiVariableBin,
+ IN UINTN HiiVariableBinSize,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
+ VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;
+
+ if (HiiVariableBin == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
+ //
+ // Do not check delete variable.
+ //
+ }
+
+ //
+ // For Hii Variable header align.
+ //
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (HiiVariableBin);
+ while ((UINTN)HiiVariable < ((UINTN)HiiVariableBin + HiiVariableBinSize)) {
+ if ((StrCmp ((CHAR16 *)(HiiVariable + 1), VariableName) == 0) &&
+ (CompareGuid (&HiiVariable->Guid, VendorGuid)))
+ {
+ //
+ // Found the Hii Variable that could be used to do check.
+ //
+ DEBUG ((DEBUG_INFO, "VarCheckHiiVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName, VendorGuid, Attributes, DataSize));
+ if (HiiVariable->Attributes != Attributes) {
+ DEBUG ((DEBUG_INFO, "VarCheckHiiVariable fail for Attributes - 0x%08x\n", HiiVariable->Attributes));
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ if (DataSize == 0) {
+ DEBUG ((DEBUG_INFO, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));
+ return EFI_SUCCESS;
+ }
+
+ if (HiiVariable->Size != DataSize) {
+ DEBUG ((DEBUG_INFO, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable->Size));
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ //
+ // Do the check.
+ // For Hii Question header align.
+ //
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->HeaderLength));
+ while ((UINTN)HiiQuestion < ((UINTN)HiiVariable + HiiVariable->Length)) {
+ if (!VarCheckHiiQuestion (HiiQuestion, Data, DataSize)) {
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ //
+ // For Hii Question header align.
+ //
+ HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiQuestion + HiiQuestion->Length));
+ }
+
+ DEBUG ((DEBUG_INFO, "VarCheckHiiVariable - ALL CHECK PASS!\n"));
+ return EFI_SUCCESS;
+ }
+
+ //
+ // For Hii Variable header align.
+ //
+ HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->Length));
+ }
+
+ // Not found, so pass.
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.h b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.h
new file mode 100644
index 0000000..06249f0
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibCommon.h
@@ -0,0 +1,43 @@
+/** @file
+ Var Check Hii Lib Common logic
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef VAR_CHECK_HII_LIB_GUID_H_
+#define VAR_CHECK_HII_LIB_GUID_H_
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Protocol/MmCommunication.h>
+#include <Library/VarCheckLib.h>
+
+#include "VarCheckHii.h"
+
+/**
+ SetVariable check handler HII.
+ @param[in] HiiVariableBin Variable BIN.
+ @param[in] HiiVariableBinSize The size of Variable BIN.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] Attributes Attribute value of the variable.
+ @param[in] DataSize Size of Data to set.
+ @param[in] Data Data pointer.
+ @retval EFI_SUCCESS The SetVariable check result was success.
+ @retval EFI_SECURITY_VIOLATION Check fail.
+**/
+EFI_STATUS
+EFIAPI
+CheckHiiVariableCommon (
+ IN VAR_CHECK_HII_VARIABLE_HEADER *HiiVariableBin,
+ IN UINTN HiiVariableBinSize,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+#endif
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.c
new file mode 100644
index 0000000..9ba75b7
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.c
@@ -0,0 +1,138 @@
+/** @file
+ VarCheckHiiLib Dependency library.
+ It sends HII variable checking data to SMM via the MM Communication protocol.
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Protocol/MmCommunication.h>
+#include <Guid/PiSmmCommunicationRegionTable.h>
+#include "InternalVarCheckStructure.h"
+#include "VarCheckHiiGen.h"
+#include "VarCheckHii.h"
+#include <Library/UefiLib.h>
+#include <Guid/EventGroup.h>
+
+extern VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin;
+extern UINTN mVarCheckHiiBinSize;
+EFI_GUID gVarCheckReceivedHiiBinHandlerGuid = VAR_CHECK_RECEIVED_HII_BIN_HANDLER_GUID;
+
+/**
+ Sends HII variable checking data to SMM at the end of DXE phase.
+ This function is triggered by the End of DXE. It locates a memory
+ region for MM communication, prepares the communication buffer with HII variable
+ checking data, and communicates with SMM using the MM Communication protocol.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context The pointer to the notification function's context, which
+ is implementation-dependent.
+**/
+VOID
+EFIAPI
+VarCheckHiiLibSmmEndOfDxeNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATION_PROTOCOL *MmCommunication;
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;
+ EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
+ EFI_MEMORY_DESCRIPTOR *MmCommMemRegion;
+ UINTN CommBufferSize;
+ UINTN Index;
+ VAR_CHECK_HII_VARIABLE_HEADER *VarCheckHiiVariable;
+
+ DEBUG ((DEBUG_INFO, "%a starts.\n", __func__));
+ VarCheckHiiGen ();
+ if ((mVarCheckHiiBinSize == 0) || (mVarCheckHiiBin == NULL)) {
+ DEBUG ((DEBUG_INFO, "%a: mVarCheckHiiBinSize = 0x%x, mVarCheckHiiBin = 0x%x \n", __func__, mVarCheckHiiBinSize, mVarCheckHiiBin));
+ return;
+ }
+
+ //
+ // Retrieve SMM Communication Region Table
+ //
+ Status = EfiGetSystemConfigurationTable (
+ &gEdkiiPiSmmCommunicationRegionTableGuid,
+ (VOID **)&PiSmmCommunicationRegionTable
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to get PiSmmCommunicationRegionTable - %r\n", __func__, Status));
+ return;
+ }
+
+ ASSERT (PiSmmCommunicationRegionTable != NULL);
+ //
+ // Find a memory region for MM communication
+ //
+ CommBufferSize = 0;
+ MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1);
+ for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
+ if (MmCommMemRegion->Type == EfiConventionalMemory) {
+ CommBufferSize = EFI_PAGES_TO_SIZE ((UINTN)MmCommMemRegion->NumberOfPages);
+ if (CommBufferSize >= (sizeof (EFI_MM_COMMUNICATE_HEADER) + mVarCheckHiiBinSize)) {
+ break;
+ }
+ }
+
+ MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MmCommMemRegion + PiSmmCommunicationRegionTable->DescriptorSize);
+ }
+
+ if (Index >= PiSmmCommunicationRegionTable->NumberOfEntries) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to find a suitable memory region for MM communication!\n", __func__));
+ return;
+ }
+
+ //
+ // Prepare the communication buffer
+ //
+ CommHeader = (EFI_MM_COMMUNICATE_HEADER *)(UINTN)MmCommMemRegion->PhysicalStart;
+ CommBufferSize = OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data) + mVarCheckHiiBinSize;
+ ZeroMem (CommHeader, CommBufferSize);
+ CopyGuid (&CommHeader->HeaderGuid, &gVarCheckReceivedHiiBinHandlerGuid);
+ CommHeader->MessageLength = mVarCheckHiiBinSize;
+ VarCheckHiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)(CommHeader->Data);
+ CopyMem (VarCheckHiiVariable, mVarCheckHiiBin, mVarCheckHiiBinSize);
+ //
+ // Locate the MM Communication protocol and signal SMI
+ //
+ Status = gBS->LocateProtocol (&gEfiMmCommunicationProtocolGuid, NULL, (VOID **)&MmCommunication);
+
+ if (!EFI_ERROR (Status)) {
+ Status = MmCommunication->Communicate (MmCommunication, CommHeader, &CommBufferSize);
+ DEBUG ((DEBUG_INFO, "%a: Communicate to smm environment = %r\n", __func__, Status));
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to locate MmCommunication protocol - %r\n", __func__, Status));
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a ends.\n", __func__));
+ return;
+}
+
+/**
+ Constructor function of the VarCheckHiiLibMmDependency.
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the Management mode System Table.
+ @retval EFI_SUCCESS The protocol was successfully installed into the DXE database.
+**/
+EFI_STATUS
+EFIAPI
+VarCheckHiiLibMmDependencyConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT Event;
+
+ DEBUG ((DEBUG_INFO, "%a starts.\n", __func__));
+ Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, VarCheckHiiLibSmmEndOfDxeNotify, NULL, &gEfiEndOfDxeEventGroupGuid, &Event);
+ ASSERT_EFI_ERROR (Status);
+ DEBUG ((DEBUG_INFO, "%a ends.\n", __func__));
+ return Status;
+}
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.inf b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.inf
new file mode 100644
index 0000000..9798a1b
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.inf
@@ -0,0 +1,53 @@
+## @file
+# VarCheckHiiLib Dependency library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = VarCheckHiiLibMmDependency
+ FILE_GUID = DF61C3DC-B08C-44B7-B771-9E4BCBBE0811
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = NULL
+ CONSTRUCTOR = VarCheckHiiLibMmDependencyConstructor
+
+[Sources]
+ VarCheckHiiLibMmDependency.c
+ VarCheckHii.h
+ VarCheckHiiGenFromFv.c
+ VarCheckHiiGenFromHii.c
+ VarCheckHiiGen.c
+ VarCheckHiiGen.h
+ InternalVarCheckStructure.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ UefiBootServicesTableLib
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiLib
+ PcdLib
+
+[Guids]
+ gEdkiiIfrBitVarstoreGuid
+ gEfiEndOfDxeEventGroupGuid
+ gEdkiiPiSmmCommunicationRegionTableGuid
+
+[Protocols]
+ gEfiMmEndOfDxeProtocolGuid
+ gEfiMmCommunicationProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiFirmwareVolumeBlock2ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiHiiDatabaseProtocolGuid ## SOMETIMES_CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVarCheckVfrDriverGuidArray ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c
deleted file mode 100644
index ee2d98c..0000000
--- a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibNullClass.c
+++ /dev/null
@@ -1,630 +0,0 @@
-/** @file
- Var Check Hii handler.
-
-Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "VarCheckHii.h"
-
-GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mVarCheckHiiHex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
-
-/**
- Dump some hexadecimal data.
-
- @param[in] Indent How many spaces to indent the output.
- @param[in] Offset The offset of the dump.
- @param[in] DataSize The size in bytes of UserData.
- @param[in] UserData The data to dump.
-
-**/
-VOID
-VarCheckHiiInternalDumpHex (
- IN UINTN Indent,
- IN UINTN Offset,
- IN UINTN DataSize,
- IN VOID *UserData
- )
-{
- UINT8 *Data;
-
- CHAR8 Val[50];
-
- CHAR8 Str[20];
-
- UINT8 TempByte;
- UINTN Size;
- UINTN Index;
-
- Data = UserData;
- while (DataSize != 0) {
- Size = 16;
- if (Size > DataSize) {
- Size = DataSize;
- }
-
- for (Index = 0; Index < Size; Index += 1) {
- TempByte = Data[Index];
- Val[Index * 3 + 0] = mVarCheckHiiHex[TempByte >> 4];
- Val[Index * 3 + 1] = mVarCheckHiiHex[TempByte & 0xF];
- Val[Index * 3 + 2] = (CHAR8)((Index == 7) ? '-' : ' ');
- Str[Index] = (CHAR8)((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
- }
-
- Val[Index * 3] = 0;
- Str[Index] = 0;
- DEBUG ((DEBUG_INFO, "%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str));
-
- Data += Size;
- Offset += Size;
- DataSize -= Size;
- }
-}
-
-/**
- Var Check Hii Question.
-
- @param[in] HiiQuestion Pointer to Hii Question
- @param[in] Data Data pointer.
- @param[in] DataSize Size of Data to set.
-
- @retval TRUE Check pass
- @retval FALSE Check fail.
-
-**/
-BOOLEAN
-VarCheckHiiQuestion (
- IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion,
- IN VOID *Data,
- IN UINTN DataSize
- )
-{
- UINT64 OneData;
- UINT64 Minimum;
- UINT64 Maximum;
- UINT64 OneValue;
- UINT8 *Ptr;
- UINT8 Index;
- UINT8 MaxContainers;
- UINT8 StartBit;
- UINT8 EndBit;
- UINT8 TotalBits;
- UINT16 VarOffsetByteLevel;
- UINT8 StorageWidthByteLevel;
-
- if (HiiQuestion->BitFieldStore) {
- VarOffsetByteLevel = HiiQuestion->VarOffset / 8;
- TotalBits = HiiQuestion->VarOffset % 8 + HiiQuestion->StorageWidth;
- StorageWidthByteLevel = (TotalBits % 8 == 0 ? TotalBits / 8 : TotalBits / 8 + 1);
- } else {
- VarOffsetByteLevel = HiiQuestion->VarOffset;
- StorageWidthByteLevel = HiiQuestion->StorageWidth;
- }
-
- if (((UINT32)VarOffsetByteLevel + StorageWidthByteLevel) > DataSize) {
- DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x)) > Size(0x%x)\n", VarOffsetByteLevel, StorageWidthByteLevel, DataSize));
- return FALSE;
- }
-
- OneData = 0;
- CopyMem (&OneData, (UINT8 *)Data + VarOffsetByteLevel, StorageWidthByteLevel);
- if (HiiQuestion->BitFieldStore) {
- //
- // Get the value from the bit field.
- //
- StartBit = HiiQuestion->VarOffset % 8;
- EndBit = StartBit + HiiQuestion->StorageWidth - 1;
- OneData = BitFieldRead64 (OneData, StartBit, EndBit);
- }
-
- switch (HiiQuestion->OpCode) {
- case EFI_IFR_ONE_OF_OP:
- Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ONEOF *)HiiQuestion + 1);
- while ((UINTN)Ptr < (UINTN)HiiQuestion + HiiQuestion->Length) {
- OneValue = 0;
- if (HiiQuestion->BitFieldStore) {
- //
- // For OneOf stored in bit field, the value of options are saved as UINT32 type.
- //
- CopyMem (&OneValue, Ptr, sizeof (UINT32));
- } else {
- CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
- }
-
- if (OneData == OneValue) {
- //
- // Match
- //
- break;
- }
-
- if (HiiQuestion->BitFieldStore) {
- Ptr += sizeof (UINT32);
- } else {
- Ptr += HiiQuestion->StorageWidth;
- }
- }
-
- if ((UINTN)Ptr >= ((UINTN)HiiQuestion + HiiQuestion->Length)) {
- //
- // No match
- //
- DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: OneOf mismatch (0x%lx)\n", OneData));
- DEBUG_CODE (
- VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
- );
- return FALSE;
- }
-
- break;
-
- case EFI_IFR_CHECKBOX_OP:
- if ((OneData != 0) && (OneData != 1)) {
- DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: CheckBox mismatch (0x%lx)\n", OneData));
- DEBUG_CODE (
- VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
- );
- return FALSE;
- }
-
- break;
-
- case EFI_IFR_NUMERIC_OP:
- Minimum = 0;
- Maximum = 0;
- Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_NUMERIC *)HiiQuestion + 1);
- if (HiiQuestion->BitFieldStore) {
- //
- // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
- //
- CopyMem (&Minimum, Ptr, sizeof (UINT32));
- Ptr += sizeof (UINT32);
- CopyMem (&Maximum, Ptr, sizeof (UINT32));
- Ptr += sizeof (UINT32);
- } else {
- CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);
- Ptr += HiiQuestion->StorageWidth;
- CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);
- Ptr += HiiQuestion->StorageWidth;
- }
-
- //
- // No need to check Step, because it is ONLY for UI.
- //
- if ((OneData < Minimum) || (OneData > Maximum)) {
- DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: Numeric mismatch (0x%lx)\n", OneData));
- DEBUG_CODE (
- VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
- );
- return FALSE;
- }
-
- break;
-
- case EFI_IFR_ORDERED_LIST_OP:
- MaxContainers = ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion)->MaxContainers;
- if (((UINT32)HiiQuestion->VarOffset + HiiQuestion->StorageWidth * MaxContainers) > DataSize) {
- DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: (VarOffset(0x%04x) + StorageWidth(0x%02x) * MaxContainers(0x%02x)) > Size(0x%x)\n", HiiQuestion->VarOffset, HiiQuestion->StorageWidth, MaxContainers, DataSize));
- return FALSE;
- }
-
- for (Index = 0; Index < MaxContainers; Index++) {
- OneData = 0;
- CopyMem (&OneData, (UINT8 *)Data + HiiQuestion->VarOffset + HiiQuestion->StorageWidth * Index, HiiQuestion->StorageWidth);
- if (OneData == 0) {
- //
- // The value of 0 is used to determine if a particular "slot" in the array is empty.
- //
- continue;
- }
-
- Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion + 1);
- while ((UINTN)Ptr < ((UINTN)HiiQuestion + HiiQuestion->Length)) {
- OneValue = 0;
- CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
- if (OneData == OneValue) {
- //
- // Match
- //
- break;
- }
-
- Ptr += HiiQuestion->StorageWidth;
- }
-
- if ((UINTN)Ptr >= ((UINTN)HiiQuestion + HiiQuestion->Length)) {
- //
- // No match
- //
- DEBUG ((DEBUG_INFO, "VarCheckHiiQuestion fail: OrderedList mismatch\n"));
- DEBUG_CODE (
- VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->StorageWidth * MaxContainers, (UINT8 *)Data + HiiQuestion->VarOffset);
- );
- DEBUG_CODE (
- VarCheckHiiInternalDumpHex (2, 0, HiiQuestion->Length, (UINT8 *)HiiQuestion);
- );
- return FALSE;
- }
- }
-
- break;
-
- default:
- ASSERT (FALSE);
- break;
- }
-
- return TRUE;
-}
-
-VAR_CHECK_HII_VARIABLE_HEADER *mVarCheckHiiBin = NULL;
-UINTN mVarCheckHiiBinSize = 0;
-
-/**
- SetVariable check handler HII.
-
- @param[in] VariableName Name of Variable to set.
- @param[in] VendorGuid Variable vendor GUID.
- @param[in] Attributes Attribute value of the variable.
- @param[in] DataSize Size of Data to set.
- @param[in] Data Data pointer.
-
- @retval EFI_SUCCESS The SetVariable check result was success.
- @retval EFI_SECURITY_VIOLATION Check fail.
-
-**/
-EFI_STATUS
-EFIAPI
-SetVariableCheckHandlerHii (
- IN CHAR16 *VariableName,
- IN EFI_GUID *VendorGuid,
- IN UINT32 Attributes,
- IN UINTN DataSize,
- IN VOID *Data
- )
-{
- VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
- VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;
-
- if (mVarCheckHiiBin == NULL) {
- return EFI_SUCCESS;
- }
-
- if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
- //
- // Do not check delete variable.
- //
- return EFI_SUCCESS;
- }
-
- //
- // For Hii Variable header align.
- //
- HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (mVarCheckHiiBin);
- while ((UINTN)HiiVariable < ((UINTN)mVarCheckHiiBin + mVarCheckHiiBinSize)) {
- if ((StrCmp ((CHAR16 *)(HiiVariable + 1), VariableName) == 0) &&
- (CompareGuid (&HiiVariable->Guid, VendorGuid)))
- {
- //
- // Found the Hii Variable that could be used to do check.
- //
- DEBUG ((DEBUG_INFO, "VarCheckHiiVariable - %s:%g with Attributes = 0x%08x Size = 0x%x\n", VariableName, VendorGuid, Attributes, DataSize));
- if (HiiVariable->Attributes != Attributes) {
- DEBUG ((DEBUG_INFO, "VarCheckHiiVariable fail for Attributes - 0x%08x\n", HiiVariable->Attributes));
- return EFI_SECURITY_VIOLATION;
- }
-
- if (DataSize == 0) {
- DEBUG ((DEBUG_INFO, "VarCheckHiiVariable - CHECK PASS with DataSize == 0 !\n"));
- return EFI_SUCCESS;
- }
-
- if (HiiVariable->Size != DataSize) {
- DEBUG ((DEBUG_INFO, "VarCheckHiiVariable fail for Size - 0x%x\n", HiiVariable->Size));
- return EFI_SECURITY_VIOLATION;
- }
-
- //
- // Do the check.
- // For Hii Question header align.
- //
- HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->HeaderLength));
- while ((UINTN)HiiQuestion < ((UINTN)HiiVariable + HiiVariable->Length)) {
- if (!VarCheckHiiQuestion (HiiQuestion, Data, DataSize)) {
- return EFI_SECURITY_VIOLATION;
- }
-
- //
- // For Hii Question header align.
- //
- HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiQuestion + HiiQuestion->Length));
- }
-
- DEBUG ((DEBUG_INFO, "VarCheckHiiVariable - ALL CHECK PASS!\n"));
- return EFI_SUCCESS;
- }
-
- //
- // For Hii Variable header align.
- //
- HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->Length));
- }
-
- // Not found, so pass.
- return EFI_SUCCESS;
-}
-
-#ifdef DUMP_VAR_CHECK_HII
-GLOBAL_REMOVE_IF_UNREFERENCED VAR_CHECK_HII_OPCODE_STRING mHiiOpCodeStringTable[] = {
- { EFI_IFR_VARSTORE_EFI_OP, "EfiVarStore" },
- { EFI_IFR_ONE_OF_OP, "OneOf" },
- { EFI_IFR_CHECKBOX_OP, "CheckBox" },
- { EFI_IFR_NUMERIC_OP, "Numeric" },
- { EFI_IFR_ORDERED_LIST_OP, "OrderedList" },
-};
-
-/**
- HII opcode to string.
-
- @param[in] HiiOpCode Hii OpCode.
-
- @return Pointer to string.
-
-**/
-CHAR8 *
-HiiOpCodeToStr (
- IN UINT8 HiiOpCode
- )
-{
- UINTN Index;
-
- for (Index = 0; Index < ARRAY_SIZE (mHiiOpCodeStringTable); Index++) {
- if (mHiiOpCodeStringTable[Index].HiiOpCode == HiiOpCode) {
- return mHiiOpCodeStringTable[Index].HiiOpCodeStr;
- }
- }
-
- return "<UnknownHiiOpCode>";
-}
-
-/**
- Dump Hii Question.
-
- @param[in] HiiQuestion Pointer to Hii Question.
-
-**/
-VOID
-DumpHiiQuestion (
- IN VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion
- )
-{
- UINT64 Minimum;
- UINT64 Maximum;
- UINT64 OneValue;
- UINT8 *Ptr;
-
- DEBUG ((DEBUG_INFO, " VAR_CHECK_HII_QUESTION_HEADER\n"));
- DEBUG ((DEBUG_INFO, " OpCode - 0x%02x (%a) (%a)\n", HiiQuestion->OpCode, HiiOpCodeToStr (HiiQuestion->OpCode), (HiiQuestion->BitFieldStore ? "bit level" : "byte level")));
- DEBUG ((DEBUG_INFO, " Length - 0x%02x\n", HiiQuestion->Length));
- DEBUG ((DEBUG_INFO, " VarOffset - 0x%04x (%a)\n", HiiQuestion->VarOffset, (HiiQuestion->BitFieldStore ? "bit level" : "byte level")));
- DEBUG ((DEBUG_INFO, " StorageWidth - 0x%02x (%a)\n", HiiQuestion->StorageWidth, (HiiQuestion->BitFieldStore ? "bit level" : "byte level")));
-
- switch (HiiQuestion->OpCode) {
- case EFI_IFR_ONE_OF_OP:
- Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ONEOF *)HiiQuestion + 1);
- while ((UINTN)Ptr < ((UINTN)HiiQuestion + HiiQuestion->Length)) {
- OneValue = 0;
- if (HiiQuestion->BitFieldStore) {
- //
- // For OneOf stored in bit field, the value of options are saved as UINT32 type.
- //
- CopyMem (&OneValue, Ptr, sizeof (UINT32));
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%08x\n", OneValue));
- } else {
- CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
- switch (HiiQuestion->StorageWidth) {
- case sizeof (UINT8):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%02x\n", OneValue));
- break;
- case sizeof (UINT16):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%04x\n", OneValue));
- break;
- case sizeof (UINT32):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%08x\n", OneValue));
- break;
- case sizeof (UINT64):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%016lx\n", OneValue));
- break;
- default:
- ASSERT (FALSE);
- break;
- }
- }
-
- if (HiiQuestion->BitFieldStore) {
- Ptr += sizeof (UINT32);
- } else {
- Ptr += HiiQuestion->StorageWidth;
- }
- }
-
- break;
-
- case EFI_IFR_CHECKBOX_OP:
- break;
-
- case EFI_IFR_NUMERIC_OP:
- Minimum = 0;
- Maximum = 0;
- Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_NUMERIC *)HiiQuestion + 1);
- if (HiiQuestion->BitFieldStore) {
- //
- // For Numeric stored in bit field, the value of Maximum/Minimum are saved as UINT32 type.
- //
- CopyMem (&Minimum, Ptr, sizeof (UINT32));
- Ptr += sizeof (UINT32);
- CopyMem (&Maximum, Ptr, sizeof (UINT32));
- Ptr += sizeof (UINT32);
-
- DEBUG ((DEBUG_INFO, " Minimum - 0x%08x\n", Minimum));
- DEBUG ((DEBUG_INFO, " Maximum - 0x%08x\n", Maximum));
- } else {
- CopyMem (&Minimum, Ptr, HiiQuestion->StorageWidth);
- Ptr += HiiQuestion->StorageWidth;
- CopyMem (&Maximum, Ptr, HiiQuestion->StorageWidth);
- Ptr += HiiQuestion->StorageWidth;
-
- switch (HiiQuestion->StorageWidth) {
- case sizeof (UINT8):
- DEBUG ((DEBUG_INFO, " Minimum - 0x%02x\n", Minimum));
- DEBUG ((DEBUG_INFO, " Maximum - 0x%02x\n", Maximum));
- break;
- case sizeof (UINT16):
- DEBUG ((DEBUG_INFO, " Minimum - 0x%04x\n", Minimum));
- DEBUG ((DEBUG_INFO, " Maximum - 0x%04x\n", Maximum));
- break;
- case sizeof (UINT32):
- DEBUG ((DEBUG_INFO, " Minimum - 0x%08x\n", Minimum));
- DEBUG ((DEBUG_INFO, " Maximum - 0x%08x\n", Maximum));
- break;
- case sizeof (UINT64):
- DEBUG ((DEBUG_INFO, " Minimum - 0x%016lx\n", Minimum));
- DEBUG ((DEBUG_INFO, " Maximum - 0x%016lx\n", Maximum));
- break;
- default:
- ASSERT (FALSE);
- break;
- }
- }
-
- break;
-
- case EFI_IFR_ORDERED_LIST_OP:
- DEBUG ((DEBUG_INFO, " MaxContainers - 0x%02x\n", ((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion)->MaxContainers));
- Ptr = (UINT8 *)((VAR_CHECK_HII_QUESTION_ORDEREDLIST *)HiiQuestion + 1);
- while ((UINTN)Ptr < ((UINTN)HiiQuestion + HiiQuestion->Length)) {
- OneValue = 0;
- CopyMem (&OneValue, Ptr, HiiQuestion->StorageWidth);
- switch (HiiQuestion->StorageWidth) {
- case sizeof (UINT8):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%02x\n", OneValue));
- break;
- case sizeof (UINT16):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%04x\n", OneValue));
- break;
- case sizeof (UINT32):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%08x\n", OneValue));
- break;
- case sizeof (UINT64):
- DEBUG ((DEBUG_INFO, " OneOfOption - 0x%016lx\n", OneValue));
- break;
- default:
- ASSERT (FALSE);
- break;
- }
-
- Ptr += HiiQuestion->StorageWidth;
- }
-
- break;
-
- default:
- ASSERT (FALSE);
- break;
- }
-}
-
-/**
- Dump Hii Variable.
-
- @param[in] HiiVariable Pointer to Hii Variable.
-
-**/
-VOID
-DumpHiiVariable (
- IN VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable
- )
-{
- VAR_CHECK_HII_QUESTION_HEADER *HiiQuestion;
-
- DEBUG ((DEBUG_INFO, "VAR_CHECK_HII_VARIABLE_HEADER\n"));
- DEBUG ((DEBUG_INFO, " Revision - 0x%04x\n", HiiVariable->Revision));
- DEBUG ((DEBUG_INFO, " HeaderLength - 0x%04x\n", HiiVariable->HeaderLength));
- DEBUG ((DEBUG_INFO, " Length - 0x%08x\n", HiiVariable->Length));
- DEBUG ((DEBUG_INFO, " OpCode - 0x%02x (%a)\n", HiiVariable->OpCode, HiiOpCodeToStr (HiiVariable->OpCode)));
- DEBUG ((DEBUG_INFO, " Size - 0x%04x\n", HiiVariable->Size));
- DEBUG ((DEBUG_INFO, " Attributes - 0x%08x\n", HiiVariable->Attributes));
- DEBUG ((DEBUG_INFO, " Guid - %g\n", &HiiVariable->Guid));
- DEBUG ((DEBUG_INFO, " Name - %s\n", HiiVariable + 1));
-
- //
- // For Hii Question header align.
- //
- HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->HeaderLength));
- while ((UINTN)HiiQuestion < ((UINTN)HiiVariable + HiiVariable->Length)) {
- //
- // Dump Hii Question related to the Hii Variable.
- //
- DumpHiiQuestion (HiiQuestion);
- //
- // For Hii Question header align.
- //
- HiiQuestion = (VAR_CHECK_HII_QUESTION_HEADER *)HEADER_ALIGN (((UINTN)HiiQuestion + HiiQuestion->Length));
- }
-}
-
-/**
- Dump Var Check HII.
-
- @param[in] VarCheckHiiBin Pointer to VarCheckHiiBin.
- @param[in] VarCheckHiiBinSize VarCheckHiiBin size.
-
-**/
-VOID
-DumpVarCheckHii (
- IN VOID *VarCheckHiiBin,
- IN UINTN VarCheckHiiBinSize
- )
-{
- VAR_CHECK_HII_VARIABLE_HEADER *HiiVariable;
-
- DEBUG ((DEBUG_INFO, "DumpVarCheckHii\n"));
-
- //
- // For Hii Variable header align.
- //
- HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (VarCheckHiiBin);
- while ((UINTN)HiiVariable < ((UINTN)VarCheckHiiBin + VarCheckHiiBinSize)) {
- DumpHiiVariable (HiiVariable);
- //
- // For Hii Variable header align.
- //
- HiiVariable = (VAR_CHECK_HII_VARIABLE_HEADER *)HEADER_ALIGN (((UINTN)HiiVariable + HiiVariable->Length));
- }
-}
-
-#endif
-
-/**
- Constructor function of VarCheckHiiLib to register var check HII handler.
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The constructor executed correctly.
-
-**/
-EFI_STATUS
-EFIAPI
-VarCheckHiiLibNullClassConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- VarCheckLibRegisterEndOfDxeCallback (VarCheckHiiGen);
- VarCheckLibRegisterAddressPointer ((VOID **)&mVarCheckHiiBin);
- VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii);
-
- return EFI_SUCCESS;
-}
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.c b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.c
new file mode 100644
index 0000000..ba16116
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.c
@@ -0,0 +1,152 @@
+/** @file
+
+ Implementation functions and structures for var check services.
+ This file provides functions and structures to register and handle variable checks
+ in the Standalone MM environment, specifically for HII variables.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Protocol/MmCommunication.h>
+#include <Library/VarCheckLib.h>
+
+#include "VarCheckHii.h"
+#include "VarCheckHiiLibCommon.h"
+
+//
+// In the standalone setup, mVarCheckHiiBin is used for sending, while mVarCheckHiiBinMmReceived is used for receiving,
+// while in the traditional setup, mVarCheckHiiBin is used for both sending and receiving.
+//
+VAR_CHECK_HII_VARIABLE_HEADER *mMmReceivedVarCheckHiiBin = NULL;
+UINTN mMmReceivedVarCheckHiiBinSize = 0;
+EFI_GUID gVarCheckReceivedHiiBinHandlerGuid = VAR_CHECK_RECEIVED_HII_BIN_HANDLER_GUID;
+
+/**
+ Registers a handler for HII variable checks in MM environment.
+ This function is intended to be called to register a handler for checking variables
+ in the Standalone MM environment. It allocates memory for the variable
+ check data and copies the data from the communication buffer.
+
+ @param[in] DispatchHandle The handle of the dispatch function.
+ @param[in] Context Optional context for the handler, not used in this implementation.
+ @param CommBuffer The buffer of data being passed in.
+ @param CommBufferSize The size of the data being passed in.
+ @retval EFI_SUCCESS Registration and memory allocation were successful.
+ @retval EFI_INVALID_PARAMETER The CommBuffer or CommBufferSize is NULL.
+ @retval EFI_ACCESS_DENIED The buffer size is invalid or the buffer is in an invalid location.
+ @retval EFI_OUT_OF_RESOURCES Memory allocation for the variable check data failed.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckHiiLibReceiveHiiBinHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *Context OPTIONAL,
+ IN OUT VOID *CommBuffer OPTIONAL,
+ IN OUT UINTN *CommBufferSize OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if ((DispatchHandle == NULL) || (CommBuffer == NULL) || (CommBufferSize == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mMmReceivedVarCheckHiiBinSize = *CommBufferSize;
+
+ if (mMmReceivedVarCheckHiiBinSize < sizeof (VAR_CHECK_HII_VARIABLE_HEADER)) {
+ DEBUG ((DEBUG_ERROR, "%a: MM Communication buffer size is invalid for this handler!\n", __func__));
+ return EFI_ACCESS_DENIED;
+ }
+
+ mMmReceivedVarCheckHiiBin = AllocateZeroPool (mMmReceivedVarCheckHiiBinSize);
+ if (mMmReceivedVarCheckHiiBin == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory for mVarCheckHiiBinMm\n", __func__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (mMmReceivedVarCheckHiiBin, CommBuffer, mMmReceivedVarCheckHiiBinSize);
+
+ Status = gMmst->MmiHandlerUnRegister (DispatchHandle);
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to unregister handler - %r!\n", __func__, Status));
+ return Status;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a: Handler unregistered successfully.\n", __func__));
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Sets the variable check handler for HII.
+ This function registers a handler that will be invoked for variable checks
+ in the HII environment. It allows for custom validation logic to be implemented
+ for setting HII variables.
+ @param[in] VariableName Name of Variable to set.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] Attributes Attribute value of the variable.
+ @param[in] DataSize Size of Data to set.
+ @param[in] Data Data pointer.
+
+**/
+EFI_STATUS
+EFIAPI
+SetVariableCheckHandlerHii (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ return CheckHiiVariableCommon (mMmReceivedVarCheckHiiBin, mMmReceivedVarCheckHiiBinSize, VariableName, VendorGuid, Attributes, DataSize, Data);
+}
+
+/**
+ Constructor function for variable check library in Standalone MM.
+ This function registers a handler for variable checks and sets up the environment
+ for variable checking in the Standalone MM environment.
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI system table.
+ @retval EFI_SUCCESS The constructor executed successfully.
+ @retval Others An error occurred during execution.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckHiiLibConstructorStandaloneMm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DispatchHandle;
+
+ DEBUG ((DEBUG_INFO, "%a: starts.\n", __func__));
+ //
+ // Register a handler to recieve the HII variable checking data.
+ //
+ Status = gMmst->MmiHandlerRegister (VarCheckHiiLibReceiveHiiBinHandler, &gVarCheckReceivedHiiBinHandlerGuid, &DispatchHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to register handler - %r!\n", __func__, Status));
+
+ return Status;
+ }
+
+ VarCheckLibRegisterAddressPointer ((VOID **)&mMmReceivedVarCheckHiiBin);
+ VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerHii);
+ DEBUG ((DEBUG_INFO, "%a: ends.\n", __func__));
+ return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.inf b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.inf
new file mode 100644
index 0000000..dcef802
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.inf
@@ -0,0 +1,47 @@
+## @file
+# Implementation functions and structures for var check services.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = VarCheckHiiLib
+ MODULE_UNI_FILE = VarCheckHiiLibStandaloneMm.uni
+ FILE_GUID = 8545E553-AF7D-4FA0-B402-9B5A67ABC812
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = VarCheckHiiLib|MM_STANDALONE
+ CONSTRUCTOR = VarCheckHiiLibConstructorStandaloneMm
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ VarCheckHiiLibStandaloneMm.c
+ VarCheckHii.h
+ InternalVarCheckStructure.h
+ VarCheckHiiLibCommon.c
+ VarCheckHiiLibCommon.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ VarCheckLib
+
+[Protocols]
+ gEfiMmEndOfDxeProtocolGuid
diff --git a/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.uni b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.uni
new file mode 100644
index 0000000..a84a1cc
--- /dev/null
+++ b/MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.uni
@@ -0,0 +1,15 @@
+// /** @file
+// Provides variable check services and database management.
+//
+// Provides variable check services and database management.
+//
+// Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Provides StandaloneMm variable check services and database management"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Provides StandaloneMm variable check services and database management."
diff --git a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
index 7686628..7f377f1 100644
--- a/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
+++ b/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
@@ -2,6 +2,8 @@
Business logic for Variable Policy enforcement.
Copyright (c) Microsoft Corporation.
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
+
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -107,7 +109,7 @@ IsValidVariablePolicyStructure (
// Sanitize some quick values.
if ((NewPolicy == NULL) || (NewPolicy->Size == 0) ||
- // Structure size should be at least as long as the minumum structure and a NULL string.
+ // Structure size should be at least as long as the minimum structure and a NULL string.
(NewPolicy->Size < sizeof (VARIABLE_POLICY_ENTRY)) ||
// Check for the known revision.
(NewPolicy->Version != VARIABLE_POLICY_ENTRY_REVISION))
@@ -178,7 +180,7 @@ IsValidVariablePolicyStructure (
WildcardCount = 0;
while (*CheckChar != CHAR_NULL) {
// Make sure there aren't excessive wildcards.
- if (*CheckChar == '#') {
+ if (*CheckChar == L'#') {
WildcardCount++;
if (WildcardCount > MATCH_PRIORITY_MIN) {
return FALSE;
@@ -263,7 +265,7 @@ EvaluatePolicyMatch (
// Keep going until the end of both strings.
while (PolicyName[Index] != CHAR_NULL || VariableName[Index] != CHAR_NULL) {
// If we don't have a match...
- if ((PolicyName[Index] != VariableName[Index]) || (PolicyName[Index] == '#')) {
+ if ((PolicyName[Index] != VariableName[Index]) || (PolicyName[Index] == L'#')) {
// If this is a numerical wildcard, we can consider
// it a match if we alter the priority.
if ((PolicyName[Index] == L'#') &&
@@ -918,7 +920,7 @@ GetLockOnVariableStateVariablePolicyInfo (
LocalLockOnVarStatePolicy = (VARIABLE_LOCK_ON_VAR_STATE_POLICY *)(MatchPolicy + 1);
CopyMem (VariablePolicy, LocalLockOnVarStatePolicy, sizeof (*LocalLockOnVarStatePolicy));
- if ((VariableLockPolicyVariableNameBufferSize == NULL)) {
+ if (VariableLockPolicyVariableNameBufferSize == NULL) {
if (VariableLockPolicyVariableName != NULL) {
return EFI_INVALID_PARAMETER;
}
diff --git a/MdeModulePkg/MdeModulePkg.ci.yaml b/MdeModulePkg/MdeModulePkg.ci.yaml
index a3de60a..37dc5ca 100644
--- a/MdeModulePkg/MdeModulePkg.ci.yaml
+++ b/MdeModulePkg/MdeModulePkg.ci.yaml
@@ -23,6 +23,7 @@
"8005", "UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE.UID",
"8005", "UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE.HID",
"8001", "UefiSortLibUnitTestMain",
+ "8001", "MediaSanitizeUnitTestMain",
],
## Both file path and directory path are accepted.
"IgnoreFiles": [
@@ -84,6 +85,7 @@
"gEfiPeiMmAccessPpiGuid=gPeiSmmAccessPpiGuid",
"gPeiSmmControlPpiGuid=gEfiPeiMmControlPpiGuid",
"gEfiPeiMmCommunicationPpiGuid=gEfiPeiSmmCommunicationPpiGuid",
+ "gUiAppFileGuid=UiApp",
]
},
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index e6e0139..6ccca34 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -95,6 +95,9 @@
#
TpmMeasurementLib|Include/Library/TpmMeasurementLib.h
+ ## @libraryclass Provides functions for Tdx Measurement processing
+ TdxMeasurementLib|Include/Library/TdxMeasurementLib.h
+
## @libraryclass Provides authenticated variable services.
#
AuthVariableLib|Include/Library/AuthVariableLib.h
@@ -413,6 +416,13 @@
## Include/Guid/EndofS3Resume.h
gEdkiiEndOfS3ResumeGuid = { 0x96f5296d, 0x05f7, 0x4f3c, {0x84, 0x67, 0xe4, 0x56, 0x89, 0x0e, 0x0c, 0xb5 } }
+ #
+ # Guids for NVMe Timeout Events
+ # {4754469d-6528-4dfc-84aa-8c8a03a2158b}
+ gNVMeEnableStartEventGroupGuid = { 0x4754469d, 0x6528, 0x4dfc, { 0x84, 0xaa, 0x8c, 0x8a, 0x03, 0xa2, 0x15, 0x8b } }
+ # {da383315-906b-486f-80db-847f268451e4}
+ gNVMeEnableCompleteEventGroupGuid = { 0xda383315, 0x906b, 0x486f, { 0x80, 0xdb, 0x84, 0x7f, 0x26, 0x84, 0x51, 0xe4 } }
+
## Used (similar to Variable Services) to communicate policies to the enforcement engine.
# {DA1B0D11-D1A7-46C4-9DC9-F3714875C6EB}
gVarCheckPolicyLibMmiHandlerGuid = { 0xda1b0d11, 0xd1a7, 0x46c4, { 0x9d, 0xc9, 0xf3, 0x71, 0x48, 0x75, 0xc6, 0xeb }}
@@ -475,6 +485,18 @@
## Include/Guid/VariableRuntimeCacheInfo.h
gEdkiiVariableRuntimeCacheInfoHobGuid = { 0x0f472f7d, 0x6713, 0x4915, { 0x96, 0x14, 0x5d, 0xda, 0x28, 0x40, 0x10, 0x56 }}
+ ## HOB GUID to get ACPI table after FSP is done. The ACPI table that related SOC will be pass by this HOB.
+ gAcpiTableHobGuid = { 0xf9886b57, 0x8a35, 0x455e, { 0xbb, 0xb1, 0x14, 0x65, 0x5e, 0x7b, 0xe7, 0xec }}
+
+ ## Include/Guid/MmCommBuffer.h
+ gMmCommBufferHobGuid = { 0x6c2a2520, 0x0131, 0x4aee, { 0xa7, 0x50, 0xcc, 0x38, 0x4a, 0xac, 0xe8, 0xc6 }}
+
+ ## Include/Guid/DelayedDispatch.h
+ gEfiDelayedDispatchTableGuid = { 0x4b733449, 0x8eff, 0x488c, { 0x92, 0x1a, 0x15, 0x4a, 0xda, 0x25, 0x18, 0x07 }}
+
+ ## Include/Guid/ArmFfaRxTxBufferInfo.h
+ gArmFfaRxTxBufferInfoGuid = { 0x96fd3d26, 0x6fb1, 0x11ef, { 0x8c, 0x11, 0xf3, 0xc9, 0xc5, 0x02, 0x31, 0xab } }
+
[Ppis]
## Include/Ppi/FirmwareVolumeShadowPpi.h
gEdkiiPeiFirmwareVolumeShadowPpiGuid = { 0x7dfe756c, 0xed8d, 0x4d77, {0x9e, 0xc4, 0x39, 0x9a, 0x8a, 0x81, 0x51, 0x16 } }
@@ -515,6 +537,9 @@
## Include/Ppi/UfsHostController.h
gEdkiiPeiUfsHostControllerPpiGuid = { 0xdc54b283, 0x1a77, 0x4cd6, { 0x83, 0xbb, 0xfd, 0xda, 0x46, 0x9a, 0x2e, 0xc6 }}
+ ## Include/Ppi/UfsHostControllerPlatformPpi.h
+ gEdkiiUfsHcPlatformPpiGuid = { 0x9e2bde17, 0x7df0, 0x42ea, {0x98, 0xa3, 0xf6, 0x9a, 0xf3, 0xfb, 0x2b, 0xb9 }}
+
## Include/Ppi/IpmiPpi.h
gPeiIpmiPpiGuid = { 0xa9731431, 0xd968, 0x4277, { 0xb7, 0x52, 0xa3, 0xa9, 0xa6, 0xae, 0x18, 0x98 }}
@@ -576,6 +601,10 @@
gEfiPrint2ProtocolGuid = { 0xf05976ef, 0x83f1, 0x4f3d, { 0x86, 0x19, 0xf7, 0x59, 0x5d, 0x41, 0xe5, 0x38 } }
gEfiPrint2SProtocolGuid = { 0xcc252d2, 0xc106, 0x4661, { 0xb5, 0xbd, 0x31, 0x47, 0xa4, 0xf8, 0x1f, 0x92 } }
+ ## This protocol defines the Media Clear and Sanitize operations defined by NIST
+ # Include/Protocol/MediaSanitize.h
+ gMediaSanitizeProtocolGuid = { 0x0d799a99, 0x25af, 0x429e, {0x92, 0x72, 0xd0, 0xb2, 0x7d, 0x6d, 0x5f, 0x14 } }
+
## This protocol defines the generic memory test interfaces in Dxe phase.
# Include/Protocol/GenericMemoryTest.h
gEfiGenericMemTestProtocolGuid = { 0x309DE7F1, 0x7F5E, 0x4ACE, { 0xB4, 0x9C, 0x53, 0x1B, 0xE5, 0xAA, 0x95, 0xEF }}
@@ -795,13 +824,6 @@
# @Prompt Enable ConOut GOP support.
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE|BOOLEAN|0x00010042
- ## Indicates if UGA Draw Protocol will be installed on virtual handle created by ConsplitterDxe.
- # It could be set FALSE to save size.<BR><BR>
- # TRUE - Installs UGA Draw Protocol on virtual handle created by ConsplitterDxe.<BR>
- # FALSE - Does not install UGA Draw Protocol on virtual handle created by ConsplitterDxe.<BR>
- # @Prompt Enable ConOut UGA support.
- gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|TRUE|BOOLEAN|0x00010043
-
## Indicates PeiCore will first search TE section from the PEIM to load the image, or PE32 section, when PeiCore dispatches a PEI module.
# This PCD is used to tune PEI phase performance to reduce the search image time.
# It can be set according to the generated image section type.<BR><BR>
@@ -1024,6 +1046,14 @@
# @ValidList 0x80000006 | 0x03058002
gEfiMdeModulePkgTokenSpaceGuid.PcdErrorCodeSetVariable|0x03058002|UINT32|0x30001040
+ ## Delayed Dispatch Maximum Delay in us (microseconds)
+ # Maximum delay for any particular delay request - 5 seconds
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchMaxDelayUs|5000000|UINT32|0x3000104A
+
+ ## Delayed Dispatch timeout in us (microseconds)
+ # Maximum delay when waiting for completion (ie EndOfPei) - 10 seconds
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDelayedDispatchCompletionTimeoutUs|10000000|UINT32|0x3000104B
+
## Mask to control the NULL address detection in code for different phases.
# If enabled, accessing NULL address in UEFI or SMM code can be caught.<BR><BR>
# BIT0 - Enable NULL pointer detection for UEFI.<BR>
@@ -1177,6 +1207,10 @@
# @Prompt Delay access XHCI register after it issues HCRST (us)
gEfiMdeModulePkgTokenSpaceGuid.PcdDelayXhciHCReset|2000|UINT16|0x30001060
+ ## Specifies the page count allocated for the MM communication buffer.
+ # @Prompt Defines the page allocation for the MM communication buffer; default is 128 pages (512KB).
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMmCommBufferPages|128|UINT32|0x30001061
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Dynamic type PCD can be registered callback function for Pcd setting action.
# PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
@@ -1474,8 +1508,7 @@
# OEM Reserved 0x4000000000000000<BR>
# OS Reserved 0x8000000000000000<BR>
#
- # NOTE: User must NOT set NX protection for EfiLoaderCode / EfiBootServicesCode / EfiRuntimeServicesCode. <BR>
- # User MUST set the same NX protection for EfiBootServicesData and EfiConventionalMemory. <BR>
+ # NOTE: User MUST set the same NX protection for EfiBootServicesData and EfiConventionalMemory. <BR>
#
# e.g. 0x7FD5 can be used for all memory except Code. <BR>
# e.g. 0x7BD4 can be used for all memory except Code and ACPINVS/Reserved. <BR>
@@ -1694,6 +1727,11 @@
# @Prompt SPI NOR Flash Operation Delay in Microseconds (16 us)
gEfiMdeModulePkgTokenSpaceGuid.PcdSpiNorFlashOperationDelayMicroseconds|0x00000010|UINT32|0x00000035
+ ## Indicate the default timeout value for UFS device initial completetion in microseconds.
+ #
+ # @Prompt UFS device initial completion timoeout (us), default value is 600ms.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUfsInitialCompletionTimeout|600000|UINT32|0x00000036
+
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
# This PCD could be set to 0 then console output would be at max column and max row.
@@ -2238,6 +2276,12 @@
# @Prompt The value is use for Usb Network rate limiting supported.
gEfiMdeModulePkgTokenSpaceGuid.PcdUsbNetworkRateLimitingFactor|100|UINT32|0x10000028
+ ## Define the conduit to use in ArmFfalib.
+ # Default PcdFfaLibConduitSmc == TRUE, conduit = SMC
+ # If PcdFfaLibConduitSvc == FALSE, conduit = SVC
+ # @Prompt Conduit to use in ArmFfaLib.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaLibConduitSmc|TRUE|BOOLEAN|0x10000029
+
[PcdsPatchableInModule]
## Specify memory size with page number for PEI code when
# Loading Module at Fixed Address feature is enabled.
@@ -2316,5 +2360,21 @@
# @Prompt 64bit VPD base address.
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress64|0x0|UINT64|0x00030006
+ ## This dynamic PCD holds the address of the FFA TX buffer.
+ # @Prompt FFA TX Buffer Address
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxBuffer|0x00|UINT64|0x00030009
+
+ ## This dynamic PCD holds the address of the FFA RX buffer.
+ # @Prompt FFA RX Buffer Address
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaRxBuffer|0x00|UINT64|0x0003000A
+
+ ## This dynamic PCD holds the number of pages for the FFA TX/RX buffer.
+ # @Prompt FFA TX/RX Buffer Page Count
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaTxRxPageCount|1|UINT64|0x0003000B
+
+ ## This dynamic PCD holds the information if the FFA exit boot event is registered.
+ # @Prompt FFA Exit Boot Event Registered
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFfaExitBootEventRegistered|FALSE|BOOLEAN|0x0003000C
+
[UserExtensions.TianoCore."ExtraFiles"]
MdeModulePkgExtra.uni
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index fe7ab97..0c530c7 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -2,7 +2,7 @@
# EFI/PI Reference Module Package for All Architectures
#
# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
-# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2024, Intel Corporation. All rights reserved.<BR>
# Copyright (c) Microsoft Corporation.
# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
#
@@ -92,6 +92,7 @@
PlatformBootManagerLib|MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
PciHostBridgeLib|MdeModulePkg/Library/PciHostBridgeLibNull/PciHostBridgeLibNull.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ TdxMeasurementLib|MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
@@ -178,22 +179,13 @@
MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.inf
MemLib|StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf
+ VarCheckHiiLibMmDependency|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.inf
+ VarCheckHiiLib|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
-
- #
- # It is not possible to prevent ARM compiler calls to generic intrinsic functions.
- # This library provides the instrinsic functions generated by a given compiler.
- # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
- #
- NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
-
- #
- # Since software stack checking may be heuristically enabled by the compiler
- # include BaseStackCheckLib unconditionally.
- #
- NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+ ArmSmcLib|MdePkg/Library/ArmSmcLib/ArmSmcLib.inf
+ ArmSvcLib|MdePkg/Library/ArmSvcLib/ArmSvcLib.inf
[LibraryClasses.EBC, LibraryClasses.RISCV64, LibraryClasses.LOONGARCH64]
LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
@@ -331,6 +323,7 @@
MdeModulePkg/Library/PlatformBootManagerLibNull/PlatformBootManagerLibNull.inf
MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ MdeModulePkg/Library/TdxMeasurementLibNull/TdxMeasurementLibNull.inf
MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
@@ -339,6 +332,8 @@
MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
+ MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibMmDependency.inf
+ MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLibStandaloneMm.inf
MdeModulePkg/Library/PlatformVarCleanupLib/PlatformVarCleanupLib.inf
MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.inf
@@ -510,7 +505,9 @@
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf
+ MdeModulePkg/Library/SmmCorePerformanceLib/StandaloneMmCorePerformanceLib.inf
MdeModulePkg/Library/SmmPerformanceLib/SmmPerformanceLib.inf
+ MdeModulePkg/Library/SmmPerformanceLib/StandaloneMmPerformanceLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
@@ -537,5 +534,11 @@
[Components.X64]
MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
+[Components.ARM, Components.AARCH64]
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaPeiLib.inf
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaDxeLib.inf
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmCoreLib.inf
+ MdeModulePkg/Library/ArmFfaLib/ArmFfaStandaloneMmLib.inf
+
[BuildOptions]
diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni
index 6079285..7aa8322 100644
--- a/MdeModulePkg/MdeModulePkg.uni
+++ b/MdeModulePkg/MdeModulePkg.uni
@@ -709,12 +709,6 @@
"TRUE - Installs Graphics Output Protocol on virtual handle created by ConsplitterDxe.<BR>\n"
"FALSE - Does not install Graphics Output Protocol on virtual handle created by ConsplitterDxe.<BR>"
-#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdConOutUgaSupport_PROMPT #language en-US "Enable ConOut UGA support"
-
-#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdConOutUgaSupport_HELP #language en-US "Indicates if UGA Draw Protocol will be installed on virtual handle created by ConsplitterDxe. It could be set FALSE to save size.<BR><BR>\n"
- "TRUE - Installs UGA Draw Protocol on virtual handle created by ConsplitterDxe.<BR>\n"
- "FALSE - Does not install UGA Draw Protocol on virtual handle created by ConsplitterDxe.<BR>"
-
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPeiCoreImageLoaderSearchTeSectionFirst_PROMPT #language en-US "PeiCore search TE section first"
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPeiCoreImageLoaderSearchTeSectionFirst_HELP #language en-US "Indicates PeiCore will first search TE section from the PEIM to load the image, or PE32 section, when PeiCore dispatches a PEI module. This PCD is used to tune PEI phase performance to reduce the search image time. It can be set according to the generated image section type.<BR><BR>\n"
diff --git a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
index 198cdd8..0643e38 100644
--- a/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
+++ b/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
@@ -60,7 +60,14 @@
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
}
+ MdeModulePkg/Bus/Pci/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf {
+ <LibraryClasses>
+ NvmExpressDxe|MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+ }
+
#
# Build HOST_APPLICATION Libraries
#
+ MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.inf
MdeModulePkg/Test/Mock/Library/GoogleTest/MockPciHostBridgeLib/MockPciHostBridgeLib.inf
+ MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.inf
diff --git a/MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockHiiLib.h b/MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockHiiLib.h
new file mode 100644
index 0000000..fdc88cb
--- /dev/null
+++ b/MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockHiiLib.h
@@ -0,0 +1,356 @@
+/** @file MockHiiLib.h
+ Google Test mocks for HiiLib
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MOCK_HII_LIB_H_
+#define MOCK_HII_LIB_H_
+
+#include <Library/GoogleTestLib.h>
+#include <Library/FunctionMockLib.h>
+extern "C" {
+ #include <Uefi.h>
+ #include <Library/HiiLib.h>
+}
+
+struct MockHiiLib {
+ MOCK_INTERFACE_DECLARATION (MockHiiLib);
+
+ MOCK_FUNCTION_DECLARATION (
+ VOID,
+ HiiRemovePackages,
+ (IN EFI_HII_HANDLE HiiHandle)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STRING_ID,
+ HiiSetString,
+ (IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId OPTIONAL,
+ IN CONST EFI_STRING String,
+ IN CONST CHAR8 *SupportedLanguages OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STRING,
+ HiiGetString,
+ (IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STRING,
+ HiiGetStringEx,
+ (IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language OPTIONAL,
+ IN BOOLEAN TryBestLanguage)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STRING,
+ HiiGetPackageString,
+ (IN CONST EFI_GUID *PackageListGuid,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_HII_HANDLE *,
+ HiiGetHiiHandles,
+ (IN CONST EFI_GUID *PackageListGuid OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ HiiGetFormSetFromHiiHandle,
+ (IN EFI_HII_HANDLE Handle,
+ OUT EFI_IFR_FORM_SET **Buffer,
+ OUT UINTN *BufferSize)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ CHAR8 *,
+ HiiGetSupportedLanguages,
+ (IN EFI_HII_HANDLE HiiHandle)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STRING,
+ HiiConstructConfigHdr,
+ (IN CONST EFI_GUID *Guid OPTIONAL,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN EFI_HANDLE DriverHandle)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ BOOLEAN,
+ HiiSetToDefaults,
+ (IN CONST EFI_STRING Request OPTIONAL,
+ IN UINT16 DefaultId)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ BOOLEAN,
+ HiiValidateSettings,
+ (IN CONST EFI_STRING Request OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ BOOLEAN,
+ HiiIsConfigHdrMatch,
+ (IN CONST EFI_STRING ConfigHdr,
+ IN CONST EFI_GUID *Guid OPTIONAL,
+ IN CONST CHAR16 *Name OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ BOOLEAN,
+ HiiGetBrowserData,
+ (IN CONST EFI_GUID *VariableGuid OPTIONAL,
+ IN CONST CHAR16 *VariableName OPTIONAL,
+ IN UINTN BufferSize,
+ OUT UINT8 *Buffer)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ BOOLEAN,
+ HiiSetBrowserData,
+ (IN CONST EFI_GUID *VariableGuid OPTIONAL,
+ IN CONST CHAR16 *VariableName OPTIONAL,
+ IN UINTN BufferSize,
+ IN CONST UINT8 *Buffer,
+ IN CONST CHAR16 *RequestElement OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ VOID *,
+ HiiAllocateOpCodeHandle,
+ ()
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ VOID,
+ HiiFreeOpCodeHandle,
+ (VOID *OpCodeHandle)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateRawOpCodes,
+ (IN VOID *OpCodeHandle,
+ IN UINT8 *RawBuffer,
+ IN UINTN RawBufferSize)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateEndOpCode,
+ (IN VOID *OpCodeHandle)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateOneOfOptionOpCode,
+ (IN VOID *OpCodeHandle,
+ IN UINT16 StringId,
+ IN UINT8 Flags,
+ IN UINT8 Type,
+ IN UINT64 Value)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateDefaultOpCode,
+ (IN VOID *OpCodeHandle,
+ IN UINT16 DefaultId,
+ IN UINT8 Type,
+ IN UINT64 Value)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateGuidOpCode,
+ (IN VOID *OpCodeHandle,
+ IN CONST EFI_GUID *Guid,
+ IN CONST VOID *GuidOpCode OPTIONAL,
+ IN UINTN OpCodeSize)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateActionOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN EFI_STRING_ID QuestionConfig)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateSubTitleOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 Flags,
+ IN UINT8 Scope)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateGotoOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_FORM_ID FormId,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN EFI_QUESTION_ID QuestionId)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateGotoExOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_FORM_ID RefFormId,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_QUESTION_ID RefQuestionId,
+ IN EFI_GUID *RefFormSetId OPTIONAL,
+ IN EFI_STRING_ID RefDevicePath)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateCheckBoxOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_VARSTORE_ID VarStoreId,
+ IN UINT16 VarOffset,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN UINT8 CheckBoxFlags,
+ IN VOID *DefaultsOpCodeHandle OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateNumericOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_VARSTORE_ID VarStoreId,
+ IN UINT16 VarOffset,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN UINT8 NumericFlags,
+ IN UINT64 Minimum,
+ IN UINT64 Maximum,
+ IN UINT64 Step,
+ IN VOID *DefaultsOpCodeHandle OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateStringOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_VARSTORE_ID VarStoreId,
+ IN UINT16 VarOffset,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN UINT8 StringFlags,
+ IN UINT8 MinSize,
+ IN UINT8 MaxSize,
+ IN VOID *DefaultsOpCodeHandle OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateOneOfOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_VARSTORE_ID VarStoreId,
+ IN UINT16 VarOffset,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN UINT8 OneOfFlags,
+ IN VOID *OptionsOpCodeHandle,
+ IN VOID *DefaultsOpCodeHandle OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateOrderedListOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_VARSTORE_ID VarStoreId,
+ IN UINT16 VarOffset,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN UINT8 OrderedListFlags,
+ IN UINT8 DataType,
+ IN UINT8 MaxContainers,
+ IN VOID *OptionsOpCodeHandle,
+ IN VOID *DefaultsOpCodeHandle OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateTextOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN EFI_STRING_ID TextTwo)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateDateOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_VARSTORE_ID VarStoreId OPTIONAL,
+ IN UINT16 VarOffset OPTIONAL,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN UINT8 DateFlags,
+ IN VOID *DefaultsOpCodeHandle OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ UINT8 *,
+ HiiCreateTimeOpCode,
+ (IN VOID *OpCodeHandle,
+ IN EFI_QUESTION_ID QuestionId,
+ IN EFI_VARSTORE_ID VarStoreId OPTIONAL,
+ IN UINT16 VarOffset OPTIONAL,
+ IN EFI_STRING_ID Prompt,
+ IN EFI_STRING_ID Help,
+ IN UINT8 QuestionFlags,
+ IN UINT8 TimeFlags,
+ IN VOID *DefaultsOpCodeHandle OPTIONAL)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ HiiUpdateForm,
+ (IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_GUID *FormSetGuid OPTIONAL,
+ IN EFI_FORM_ID FormId,
+ IN VOID *StartOpCodeHandle,
+ IN VOID *EndOpCodeHandle OPTIONAL)
+ );
+};
+
+#endif
diff --git a/MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockVariablePolicyHelperLib.h b/MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockVariablePolicyHelperLib.h
new file mode 100644
index 0000000..585b126
--- /dev/null
+++ b/MdeModulePkg/Test/Mock/Include/GoogleTest/Library/MockVariablePolicyHelperLib.h
@@ -0,0 +1,81 @@
+/** @file MockVariablePolicyHelper.h
+ Google Test mocks for VariablePolicyHelper
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MOCK_VARIABLE_POLICY_HELPER_LIB_H_
+#define MOCK_VARIABLE_POLICY_HELPER_LIB_H_
+
+#include <Library/GoogleTestLib.h>
+#include <Library/FunctionMockLib.h>
+extern "C" {
+ #include <Uefi.h>
+ #include <Protocol/VariablePolicy.h>
+}
+
+//
+// Declarations to handle usage of the VariablePolicyHelperLib by creating mock
+//
+struct MockVariablePolicyHelperLib {
+ MOCK_INTERFACE_DECLARATION (MockVariablePolicyHelperLib);
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ CreateBasicVariablePolicy,
+ (IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN UINT8 LockPolicyType,
+ OUT VARIABLE_POLICY_ENTRY **NewEntry)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ CreateVarStateVariablePolicy,
+ (IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN CONST EFI_GUID *VarStateNamespace,
+ IN UINT8 VarStateValue,
+ IN CONST CHAR16 *VarStateName,
+ OUT VARIABLE_POLICY_ENTRY **NewEntry)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ RegisterBasicVariablePolicy,
+ (IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN UINT8 LockPolicyType)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ RegisterVarStateVariablePolicy,
+ (IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN CONST EFI_GUID *VarStateNamespace,
+ IN CONST CHAR16 *VarStateName,
+ IN UINT8 VarStateValue)
+ );
+};
+
+#endif
diff --git a/MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.cpp b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.cpp
new file mode 100644
index 0000000..37c8f99
--- /dev/null
+++ b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.cpp
@@ -0,0 +1,49 @@
+/** @file MockHiiLib.cpp
+ Google Test mocks for HiiLib
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <GoogleTest/Library/MockHiiLib.h>
+
+//
+// Global Variables that are not const
+//
+
+MOCK_INTERFACE_DEFINITION (MockHiiLib);
+
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiRemovePackages, 1, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiSetString, 4, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiGetString, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiGetStringEx, 4, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiGetPackageString, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiGetHiiHandles, 1, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiGetFormSetFromHiiHandle, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiGetSupportedLanguages, 1, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiConstructConfigHdr, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiSetToDefaults, 2, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiValidateSettings, 1, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiIsConfigHdrMatch, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiGetBrowserData, 4, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiSetBrowserData, 5, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiAllocateOpCodeHandle, 0, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiFreeOpCodeHandle, 1, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateRawOpCodes, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateEndOpCode, 1, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateOneOfOptionOpCode, 5, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateDefaultOpCode, 4, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateGuidOpCode, 4, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateActionOpCode, 6, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateSubTitleOpCode, 5, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateGotoOpCode, 6, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateGotoExOpCode, 9, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateCheckBoxOpCode, 9, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateNumericOpCode, 12, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateStringOpCode, 11, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateOneOfOpCode, 10, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateOrderedListOpCode, 12, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateTextOpCode, 4, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateDateOpCode, 9, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiCreateTimeOpCode, 9, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHiiLib, HiiUpdateForm, 5, EFIAPI);
diff --git a/MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.inf b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.inf
new file mode 100644
index 0000000..a6baa48
--- /dev/null
+++ b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockHiiLib/MockHiiLib.inf
@@ -0,0 +1,34 @@
+## @file MockHiiLib.inf
+# Google Test mocks for HiiLib
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MockHiiLib
+ FILE_GUID = d29d29fa-e62f-543a-8d6d-793858ac7f35
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = HiiLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MockHiiLib.cpp
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+ GoogleTestLib
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /EHs /bigobj
diff --git a/MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.cpp b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.cpp
new file mode 100644
index 0000000..413d7b6
--- /dev/null
+++ b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.cpp
@@ -0,0 +1,14 @@
+/** @file MockVariablePolicyHelperLib.cpp
+ Google Test mocks for VariablePolicyHelperLib
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <GoogleTest/Library/MockVariablePolicyHelperLib.h>
+
+MOCK_INTERFACE_DEFINITION (MockVariablePolicyHelperLib);
+MOCK_FUNCTION_DEFINITION (MockVariablePolicyHelperLib, CreateBasicVariablePolicy, 8, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockVariablePolicyHelperLib, CreateVarStateVariablePolicy, 10, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockVariablePolicyHelperLib, RegisterBasicVariablePolicy, 8, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockVariablePolicyHelperLib, RegisterVarStateVariablePolicy, 10, EFIAPI);
diff --git a/MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.inf b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.inf
new file mode 100644
index 0000000..82faba5
--- /dev/null
+++ b/MdeModulePkg/Test/Mock/Library/GoogleTest/MockVariablePolicyHelperLib/MockVariablePolicyHelperLib.inf
@@ -0,0 +1,33 @@
+## @file MockVariablePolicyHelperLib.inf
+# Mock Variable Policy Library implementation.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MockVariablePolicyHelperLib
+ FILE_GUID = 251633CE-1FE7-4500-BF0A-CF3B2B52B9EE
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VariablePolicyHelperLib
+ PI_SPECIFICATION_VERSION = 0x0001000A
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MockVariablePolicyHelperLib.cpp
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+ GoogleTestLib
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /EHsc
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
index 9cfef3d..3caa20d 100644
--- a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
@@ -127,6 +127,12 @@ typedef struct {
)
//
+// ACPI HOB produced by silicon initialization code will provide the RSDP structure.
+//
+typedef struct {
+ EFI_PHYSICAL_ADDRESS Rsdp;
+} ACPI_SILICON_HOB;
+//
// Protocol Constructor functions
//
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
index be498a5..8d147a3 100644
--- a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
@@ -57,6 +57,7 @@
gEfiAcpi10TableGuid ## PRODUCES ## SystemTable
gEfiAcpiTableGuid ## PRODUCES ## SystemTable
gUniversalPayloadAcpiTableGuid ## SOMETIMES_CONSUMES ## HOB
+ gAcpiTableHobGuid ## SOMETIMES_CONSUMES ## HOB
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol ## CONSUMES
diff --git a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
index 45c0ae6..56f3c8b 100644
--- a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
@@ -1948,6 +1948,227 @@ InstallAcpiTableFromHob (
}
/**
+ This function is updating the instance with RSDP and RSDT, these are steps in the constructor that will be skipped if this HOB is available.
+
+ @param AcpiTableInstance Protocol instance private data.
+ @param GuidHob GUID HOB header.
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_NOT_FOUND The function doesn't find the Rsdp from AcpiSiliconHob.
+ @return EFI_ABORTED The function could not complete successfully.
+
+**/
+EFI_STATUS
+InstallAcpiTableFromAcpiSiliconHob (
+ EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance,
+ EFI_HOB_GUID_TYPE *GuidHob
+ )
+{
+ ACPI_SILICON_HOB *AcpiSiliconHob;
+ EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *SiAcpiHobRsdp;
+ EFI_ACPI_DESCRIPTION_HEADER *SiCommonAcpiTable;
+ EFI_STATUS Status;
+ UINTN NumOfTblEntries;
+ EFI_ACPI_TABLE_VERSION Version;
+ UINT64 SocTablePtr;
+ EFI_ACPI_DESCRIPTION_HEADER *SocEntryTable;
+ UINTN Index;
+ UINTN TableKey;
+ VOID *NeedToInstallTable;
+ UINT8 *Buffer;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN TotalSocTablesize;
+
+ DEBUG ((DEBUG_INFO, "InstallAcpiTableFromAcpiSiliconHob - Start\n"));
+ //
+ // Initial variable.
+ //
+ SiAcpiHobRsdp = NULL;
+ SiCommonAcpiTable = NULL;
+ AcpiSiliconHob = GET_GUID_HOB_DATA (GuidHob);
+ Status = EFI_SUCCESS;
+ Version = PcdGet32 (PcdAcpiExposedTableVersions);
+ TableKey = 0;
+ //
+ // Got RSDP table from ACPI Silicon Hob.
+ //
+ SiAcpiHobRsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)(AcpiSiliconHob->Rsdp);
+ if (SiAcpiHobRsdp == NULL) {
+ DEBUG ((DEBUG_ERROR, "InstallAcpiTableFromAcpiSiliconHob: Fail to locate RSDP Acpi table!!\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ DEBUG ((DEBUG_INFO, "Silicon ACPI RSDP address : 0x%016lx\n", SiAcpiHobRsdp));
+ AcpiTableInstance->Rsdp3 = SiAcpiHobRsdp;
+
+ //
+ // Got XSDT address from RSDP table.
+ //
+ Buffer = (UINT8 *)(UINTN)(SiAcpiHobRsdp->XsdtAddress);
+ SiCommonAcpiTable = (EFI_ACPI_DESCRIPTION_HEADER *)Buffer;
+
+ DEBUG ((DEBUG_INFO, "Silicon ACPI XSDT address : 0x%016lx\n", SiCommonAcpiTable));
+
+ if (SiCommonAcpiTable->Length <= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
+ DEBUG ((DEBUG_ERROR, "XSDT length is incorrect\n"));
+ return EFI_ABORTED;
+ }
+
+ //
+ // Calcaue 64bit Acpi table number.
+ //
+ NumOfTblEntries = (SiCommonAcpiTable->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof (UINT64);
+ DEBUG ((DEBUG_ERROR, "64bit NumOfTblEntries : 0x%x\n", NumOfTblEntries));
+ //
+ // Reserved the ACPI reclaim memory for XSDT.
+ //
+ //
+ TotalSocTablesize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + sizeof (UINT64);
+ PageAddress = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ mAcpiTableAllocType,
+ EfiACPIReclaimMemory,
+ EFI_SIZE_TO_PAGES (TotalSocTablesize),
+ &PageAddress
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to allocate EfiACPIReclaimMemory for XSDT. Status : %r\n", Status));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (&PageAddress, TotalSocTablesize);
+ AcpiTableInstance->Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)PageAddress;
+
+ //
+ // Initial XSDT table content.
+ //
+ AcpiTableInstance->Xsdt->Signature = SiCommonAcpiTable->Signature;
+ //
+ // Always reserve first one for FADT table.
+ //
+ AcpiTableInstance->Xsdt->Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + sizeof (UINT64);
+ AcpiTableInstance->Xsdt->Revision = SiCommonAcpiTable->Revision;
+ CopyMem (
+ &AcpiTableInstance->Xsdt->OemId,
+ SiCommonAcpiTable->OemId,
+ sizeof (AcpiTableInstance->Xsdt->OemId)
+ );
+ CopyMem (
+ &AcpiTableInstance->Xsdt->OemTableId,
+ &SiCommonAcpiTable->OemTableId,
+ sizeof (UINT64)
+ );
+ AcpiTableInstance->Xsdt->OemRevision = SiCommonAcpiTable->OemRevision;
+ AcpiTableInstance->Xsdt->CreatorId = SiCommonAcpiTable->CreatorId;
+ AcpiTableInstance->Xsdt->CreatorRevision = SiCommonAcpiTable->CreatorRevision;
+ AcpiTableInstance->NumberOfTableEntries3 = 1;
+ //
+ // Extract ACPI table from AcpiSiliconHob XSDT.
+ //
+ for (Index = 0; Index < NumOfTblEntries; Index++) {
+ CopyMem (&SocTablePtr, (((UINT8 *)(SiCommonAcpiTable + 1)) + ((sizeof (UINT64)) * Index)), sizeof (UINT64));
+ SocEntryTable = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)SocTablePtr;
+ //
+ // Display table information.
+ //
+ DEBUG ((DEBUG_INFO, "[%x] Table address : 0x%016lx\n", Index, SocTablePtr));
+
+ Buffer = (UINT8 *)&SocEntryTable->Signature;
+ DEBUG ((DEBUG_INFO, "Table signature = %c%c%c%c\n", Buffer[0], Buffer[1], Buffer[2], Buffer[3]));
+
+ DEBUG ((DEBUG_INFO, "Table Length : 0x%x\n", SocEntryTable->Length));
+
+ Buffer = (UINT8 *)&SocEntryTable->OemId;
+ DEBUG (
+ (DEBUG_INFO, "Table OemId = %c%c%c%c%c%c\n",
+ Buffer[0],
+ Buffer[1],
+ Buffer[2],
+ Buffer[3],
+ Buffer[4],
+ Buffer[5]
+ )
+ );
+
+ Buffer = (UINT8 *)&SocEntryTable->OemTableId;
+ DEBUG (
+ (DEBUG_INFO, "Table OemTableId = %c%c%c%c%c%c%c%c\n",
+ Buffer[0],
+ Buffer[1],
+ Buffer[2],
+ Buffer[3],
+ Buffer[4],
+ Buffer[5],
+ Buffer[6],
+ Buffer[7]
+ )
+ );
+ DEBUG ((DEBUG_INFO, "\n"));
+ //
+ // Add ACPI table in the DXE AcpiTableInstance.
+ //
+ Status = AddTableToList (AcpiTableInstance, SocEntryTable, TRUE, Version, TRUE, &TableKey);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "InstallAcpiTableFromAcpiSiliconHob: Fail to add ACPI table at 0x%p\n", SocEntryTable));
+ ASSERT_EFI_ERROR (Status);
+ break;
+ }
+
+ if (SocEntryTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
+ //
+ // According ACPI spec, if XDsdt field contains a nonzero value which can be used by the OSPM, then the Dsdt field must be ignored by the OSPM.
+ //
+ if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XDsdt != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XDsdt;
+ } else if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->Dsdt != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->Dsdt;
+ }
+
+ //
+ // if signature can not be found from the XDsdt / Dsdt field then skip it.
+ //
+ if (((EFI_ACPI_DESCRIPTION_HEADER *)NeedToInstallTable)->Signature == EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
+ Status = AddTableToList (AcpiTableInstance, NeedToInstallTable, TRUE, Version, TRUE, &TableKey);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to add DSDT in the DXE Table list!\n"));
+ ASSERT_EFI_ERROR (Status);
+ break;
+ } else {
+ DEBUG ((DEBUG_ERROR, "Installed DSDT in the DXE Table list!\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "The DSDT content is not correct, then skip it!\n"));
+ }
+
+ //
+ // According ACPI spec, if XFirmwareCtrl field contains a nonzero value which can be used by the OSPM, then the FirmwareCtrl field must be ignored by the OSPM.
+ //
+ if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XFirmwareCtrl != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->XFirmwareCtrl;
+ } else if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->FirmwareCtrl != 0) {
+ NeedToInstallTable = (VOID *)(UINTN)((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)SocEntryTable)->FirmwareCtrl;
+ }
+
+ if (((EFI_ACPI_DESCRIPTION_HEADER *)NeedToInstallTable)->Signature == EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) {
+ Status = AddTableToList (AcpiTableInstance, NeedToInstallTable, TRUE, Version, TRUE, &TableKey);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Fail to add FACS in the DXE Table list!\n"));
+ ASSERT_EFI_ERROR (Status);
+ break;
+ } else {
+ DEBUG ((DEBUG_ERROR, "Installed FACS in the DXE Table list!\n"));
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "The FACS content is not correct, then skip it!\n"));
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "InstallAcpiTableFromAcpiSiliconHob - End\n"));
+ return Status;
+}
+
+/**
Constructor for the ACPI table protocol. Initializes instance
data.
@@ -1969,6 +2190,7 @@ AcpiTableAcpiTableConstructor (
UINT8 *Pointer;
EFI_PHYSICAL_ADDRESS PageAddress;
EFI_MEMORY_TYPE AcpiAllocateMemoryType;
+ EFI_HOB_GUID_TYPE *GuidHob;
//
// Check for invalid input parameters
@@ -1996,6 +2218,23 @@ AcpiTableAcpiTableConstructor (
}
//
+ // Check Silicon ACPI Hob.
+ //
+ GuidHob = GetFirstGuidHob (&gAcpiTableHobGuid);
+ if (GuidHob != NULL) {
+ Status = InstallAcpiTableFromAcpiSiliconHob (AcpiTableInstance, GuidHob);
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "Installed ACPI Table from AcpiSiliconHob.\n"));
+ return EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, "Fail to Installed ACPI Table from AcpiSiliconHob!!\n"));
+ ASSERT (Status != EFI_SUCCESS);
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "Fail to locate AcpiSiliconHob!!\n"));
+ }
+
+ //
// Create RSDP table
//
RsdpTableSize = sizeof (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
diff --git a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
index 0ea4fb3..c7be6c5 100644
--- a/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
+++ b/MdeModulePkg/Universal/CapsuleOnDiskLoadPei/CapsuleOnDiskLoadPei.c
@@ -20,7 +20,7 @@
#include <PiPei.h>
//
-// The protocols, PPI and GUID defintions for this module
+// The protocols, PPI and GUID definitions for this module
//
#include <Ppi/MasterBootMode.h>
#include <Ppi/FirmwareVolumeInfo.h>
diff --git a/MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf b/MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
index 35d2535..8457ac3 100644
--- a/MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
+++ b/MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
@@ -44,6 +44,9 @@
DebugLib
CpuExceptionHandlerLib
DebugAgentLib
+ # CapsuleX64 implements its own _ModuleEntryPoint() and does not link against the standard PEIM entrypoint. As a
+ # result, it must include StackCheckLib to resolve the compiler inserted references to stack cookie functionality
+ StackCheckLib
[Depex]
FALSE
diff --git a/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c
index 700ea9d..a7f0225 100644
--- a/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c
+++ b/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatform.c
@@ -27,6 +27,15 @@ EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding = {
NULL
};
+//
+// Values from Usb Inteface Association Descriptor Device
+// Class Code and Usage Model specification (iadclasscode_r10.pdf)
+// from Usb.org
+//
+#define USB_BASE_CLASS_MISCELLANEOUS 0xEF
+#define USB_MISCELLANEOUS_SUBCLASS_COMMON 0x02
+#define USB_MISCELLANEOUS_PROTOCOL_IAD 0x01
+
/**
Entrypoint of this module.
@@ -808,10 +817,16 @@ MatchUsbClass (
DeviceClass = DevDesc.DeviceClass;
DeviceSubClass = DevDesc.DeviceSubClass;
DeviceProtocol = DevDesc.DeviceProtocol;
- if (DeviceClass == 0) {
+
+ if ((DeviceClass == 0) ||
+ ((DeviceClass == USB_BASE_CLASS_MISCELLANEOUS) &&
+ (DeviceSubClass == USB_MISCELLANEOUS_SUBCLASS_COMMON) &&
+ (DeviceProtocol == USB_MISCELLANEOUS_PROTOCOL_IAD)))
+ {
//
- // If Class in Device Descriptor is set to 0, use the Class, SubClass and
- // Protocol in Interface Descriptor instead.
+ // If Class in Device Descriptor is set to 0 (Device), or
+ // Class/SubClass/Protocol is 0xEF/0x02/0x01 (IAD), use the Class, SubClass
+ // and Protocol in Interface Descriptor instead.
//
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IfDesc);
if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
index 0a776f3..2dbb7ea 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
@@ -108,15 +108,6 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = {
};
//
-// Uga Draw Protocol Private Data template
-//
-GLOBAL_REMOVE_IF_UNREFERENCED EFI_UGA_DRAW_PROTOCOL mUgaDrawProtocolTemplate = {
- ConSplitterUgaDrawGetMode,
- ConSplitterUgaDrawSetMode,
- ConSplitterUgaDrawBlt
-};
-
-//
// Graphics Output Protocol Private Data template
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_GRAPHICS_OUTPUT_PROTOCOL mGraphicsOutputProtocolTemplate = {
@@ -156,22 +147,11 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = {
{
NULL,
NULL,
- NULL
- },
- 0,
- 0,
- 0,
- 0,
-
- {
- NULL,
- NULL,
NULL,
NULL
},
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *)NULL,
0,
- 0,
0,
(TEXT_OUT_AND_GOP_DATA *)NULL,
@@ -212,22 +192,11 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = {
{
NULL,
NULL,
- NULL
- },
- 0,
- 0,
- 0,
- 0,
-
- {
- NULL,
- NULL,
NULL,
NULL
},
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *)NULL,
0,
- 0,
0,
(TEXT_OUT_AND_GOP_DATA *)NULL,
@@ -422,7 +391,7 @@ ToggleStateSyncReInitialization (
Installs driver module protocols and. Creates virtual device handles for ConIn,
ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
- Installs Graphics Output protocol and/or UGA Draw protocol if needed.
+ Installs Graphics Output protocol.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@@ -494,12 +463,9 @@ ConSplitterDriverEntry (
ASSERT_EFI_ERROR (Status);
//
- // Either Graphics Output protocol or UGA Draw protocol must be supported.
+ // Graphics Output protocol must be supported.
//
- ASSERT (
- FeaturePcdGet (PcdConOutGopSupport) ||
- FeaturePcdGet (PcdConOutUgaSupport)
- );
+ ASSERT (FeaturePcdGet (PcdConOutGopSupport));
//
// The driver creates virtual handles for ConIn, ConOut, StdErr.
@@ -757,10 +723,6 @@ ConSplitterTextOutConstructor (
//
// Copy protocols template
//
- if (FeaturePcdGet (PcdConOutUgaSupport)) {
- CopyMem (&ConOutPrivate->UgaDraw, &mUgaDrawProtocolTemplate, sizeof (EFI_UGA_DRAW_PROTOCOL));
- }
-
if (FeaturePcdGet (PcdConOutGopSupport)) {
CopyMem (&ConOutPrivate->GraphicsOutput, &mGraphicsOutputProtocolTemplate, sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL));
}
@@ -806,13 +768,6 @@ ConSplitterTextOutConstructor (
ConOutPrivate->TextOutQueryData[0].Rows = 25;
TextOutSetMode (ConOutPrivate, 0);
- if (FeaturePcdGet (PcdConOutUgaSupport)) {
- //
- // Setup the UgaDraw to 800 x 600 x 32 bits per pixel, 60Hz.
- //
- ConSplitterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60);
- }
-
if (FeaturePcdGet (PcdConOutGopSupport)) {
//
// Setup resource for mode information in Graphics Output Protocol interface
@@ -1335,7 +1290,6 @@ ConSplitterConOutDriverBindingStart (
EFI_STATUS Status;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
UINTN SizeOfInfo;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
@@ -1356,7 +1310,6 @@ ConSplitterConOutDriverBindingStart (
}
GraphicsOutput = NULL;
- UgaDraw = NULL;
//
// Try to Open Graphics Output protocol
//
@@ -1369,20 +1322,6 @@ ConSplitterConOutDriverBindingStart (
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
- if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
- //
- // Open UGA DRAW protocol
- //
- gBS->OpenProtocol (
- ControllerHandle,
- &gEfiUgaDrawProtocolGuid,
- (VOID **)&UgaDraw,
- This->DriverBindingHandle,
- mConOut.VirtualHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- }
-
//
// When new console device is added, the new mode will be set later,
// so put current mode back to init state.
@@ -1393,36 +1332,18 @@ ConSplitterConOutDriverBindingStart (
// If both ConOut and StdErr incorporate the same Text Out device,
// their MaxMode and QueryData should be the intersection of both.
//
- Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput, UgaDraw);
+ Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, GraphicsOutput);
ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
- if (FeaturePcdGet (PcdConOutUgaSupport)) {
- //
- // Get the UGA mode data of ConOut from the current mode
- //
- if (GraphicsOutput != NULL) {
- Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- ASSERT (SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
-
- mConOut.UgaHorizontalResolution = Info->HorizontalResolution;
- mConOut.UgaVerticalResolution = Info->VerticalResolution;
- mConOut.UgaColorDepth = 32;
- mConOut.UgaRefreshRate = 60;
-
- FreePool (Info);
- } else if (UgaDraw != NULL) {
- Status = UgaDraw->GetMode (
- UgaDraw,
- &mConOut.UgaHorizontalResolution,
- &mConOut.UgaVerticalResolution,
- &mConOut.UgaColorDepth,
- &mConOut.UgaRefreshRate
- );
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
+
+ ASSERT (SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+
+ FreePool (Info);
}
return Status;
@@ -1477,7 +1398,7 @@ ConSplitterStdErrDriverBindingStart (
// If both ConOut and StdErr incorporate the same Text Out device,
// their MaxMode and QueryData should be the intersection of both.
//
- Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);
+ Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL);
ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
return Status;
@@ -2737,7 +2658,6 @@ ConSplitterGetIntersectionBetweenConOutAndStrErr (
@param Private Text Out Splitter pointer.
@param GraphicsOutput Graphics Output protocol pointer.
- @param UgaDraw UGA Draw protocol pointer.
@retval EFI_SUCCESS Output mode added successfully.
@retval other Failed to add output mode.
@@ -2746,8 +2666,7 @@ ConSplitterGetIntersectionBetweenConOutAndStrErr (
EFI_STATUS
ConSplitterAddGraphicsOutputMode (
IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
- IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
)
{
EFI_STATUS Status;
@@ -2762,12 +2681,8 @@ ConSplitterAddGraphicsOutputMode (
UINTN NumberIndex;
BOOLEAN Match;
BOOLEAN AlreadyExist;
- UINT32 UgaHorizontalResolution;
- UINT32 UgaVerticalResolution;
- UINT32 UgaColorDepth;
- UINT32 UgaRefreshRate;
- ASSERT (GraphicsOutput != NULL || UgaDraw != NULL);
+ ASSERT (GraphicsOutput != NULL);
CurrentGraphicsOutputMode = Private->GraphicsOutput.Mode;
@@ -2775,15 +2690,6 @@ ConSplitterAddGraphicsOutputMode (
CurrentIndex = 0;
Status = EFI_SUCCESS;
- if (Private->CurrentNumberOfUgaDraw != 0) {
- //
- // If any UGA device has already been added, then there is no need to
- // calculate intersection of display mode of different GOP/UGA device,
- // since only one display mode will be exported (i.e. user-defined mode)
- //
- goto Done;
- }
-
if (GraphicsOutput != NULL) {
if (Private->CurrentNumberOfGraphicsOutput == 0) {
//
@@ -2937,51 +2843,12 @@ ConSplitterAddGraphicsOutputMode (
}
}
}
- } else if (UgaDraw != NULL) {
- //
- // Graphics console driver can ensure the same mode for all GOP devices
- // so we can get the current mode from this video device
- //
- UgaDraw->GetMode (
- UgaDraw,
- &UgaHorizontalResolution,
- &UgaVerticalResolution,
- &UgaColorDepth,
- &UgaRefreshRate
- );
-
- CurrentGraphicsOutputMode->MaxMode = 1;
- Info = CurrentGraphicsOutputMode->Info;
- Info->Version = 0;
- Info->HorizontalResolution = UgaHorizontalResolution;
- Info->VerticalResolution = UgaVerticalResolution;
- Info->PixelFormat = PixelBltOnly;
- Info->PixelsPerScanLine = UgaHorizontalResolution;
- CurrentGraphicsOutputMode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
- CurrentGraphicsOutputMode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS)(UINTN)NULL;
- CurrentGraphicsOutputMode->FrameBufferSize = 0;
-
- //
- // Update the private mode buffer
- //
- CopyMem (&Private->GraphicsOutputModeBuffer[0], Info, sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
-
- //
- // Only mode 0 is available to be set
- //
- CurrentIndex = 0;
}
-Done:
-
if (GraphicsOutput != NULL) {
Private->CurrentNumberOfGraphicsOutput++;
}
- if (UgaDraw != NULL) {
- Private->CurrentNumberOfUgaDraw++;
- }
-
//
// Force GraphicsOutput mode to be set,
//
@@ -3130,7 +2997,6 @@ ConsplitterSetConsoleOutMode (
@param Private Text Out Splitter pointer.
@param TextOut Simple Text Output protocol pointer.
@param GraphicsOutput Graphics Output protocol pointer.
- @param UgaDraw UGA Draw protocol pointer.
@retval EFI_SUCCESS Text Output Device added successfully.
@retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
@@ -3140,17 +3006,12 @@ EFI_STATUS
ConSplitterTextOutAddDevice (
IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
- IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
)
{
EFI_STATUS Status;
UINTN CurrentNumOfConsoles;
INT32 MaxMode;
- UINT32 UgaHorizontalResolution;
- UINT32 UgaVerticalResolution;
- UINT32 UgaColorDepth;
- UINT32 UgaRefreshRate;
TEXT_OUT_AND_GOP_DATA *TextAndGop;
UINTN SizeOfInfo;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
@@ -3186,7 +3047,6 @@ ConSplitterTextOutAddDevice (
TextAndGop->TextOut = TextOut;
TextAndGop->GraphicsOutput = GraphicsOutput;
- TextAndGop->UgaDraw = UgaDraw;
if (CurrentNumOfConsoles == 0) {
//
@@ -3215,101 +3075,33 @@ ConSplitterTextOutAddDevice (
//
// This device display mode will be added into Graphics Ouput modes.
//
- if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {
- DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);
+ if (GraphicsOutput != NULL) {
+ DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput);
}
- if (FeaturePcdGet (PcdConOutUgaSupport)) {
- //
- // If UGA is produced by Consplitter
- //
- if (GraphicsOutput != NULL) {
- Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- ASSERT (SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
-
- UgaHorizontalResolution = Info->HorizontalResolution;
- UgaVerticalResolution = Info->VerticalResolution;
-
- FreePool (Info);
- } else if (UgaDraw != NULL) {
- Status = UgaDraw->GetMode (
- UgaDraw,
- &UgaHorizontalResolution,
- &UgaVerticalResolution,
- &UgaColorDepth,
- &UgaRefreshRate
- );
- if (!EFI_ERROR (Status) && EFI_ERROR (DeviceStatus)) {
- //
- // if GetMode is successfully and UGA device hasn't been set, set it
- //
- Status = ConSplitterUgaDrawSetMode (
- &Private->UgaDraw,
- UgaHorizontalResolution,
- UgaVerticalResolution,
- UgaColorDepth,
- UgaRefreshRate
- );
- }
-
- //
- // If GetMode/SetMode is failed, set to 800x600 mode
- //
- if (EFI_ERROR (Status)) {
- Status = ConSplitterUgaDrawSetMode (
- &Private->UgaDraw,
- 800,
- 600,
- 32,
- 60
- );
- }
+ if (GraphicsOutput != NULL) {
+ Status = GraphicsOutput->QueryMode (GraphicsOutput, GraphicsOutput->Mode->Mode, &SizeOfInfo, &Info);
+ if (EFI_ERROR (Status)) {
+ return Status;
}
+
+ ASSERT (SizeOfInfo <= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+ FreePool (Info);
}
if (((!EFI_ERROR (DeviceStatus)) || (!EFI_ERROR (Status))) &&
- ((Private->CurrentNumberOfGraphicsOutput + Private->CurrentNumberOfUgaDraw) == 1))
+ ((Private->CurrentNumberOfGraphicsOutput) == 1))
{
- if (!FeaturePcdGet (PcdConOutGopSupport)) {
- //
- // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed
- // on the virtual handle.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mConOut.VirtualHandle,
- &gEfiUgaDrawProtocolGuid,
- &mConOut.UgaDraw,
- NULL
- );
- } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
- //
- // If UGA Draw protocol not supported, Graphics Output Protocol is installed
- // on virtual handle.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mConOut.VirtualHandle,
- &gEfiGraphicsOutputProtocolGuid,
- &mConOut.GraphicsOutput,
- NULL
- );
- } else {
- //
- // Boot Graphics Output protocol and UGA Draw protocol are supported,
- // both they will be installed on virtual handle.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &mConOut.VirtualHandle,
- &gEfiGraphicsOutputProtocolGuid,
- &mConOut.GraphicsOutput,
- &gEfiUgaDrawProtocolGuid,
- &mConOut.UgaDraw,
- NULL
- );
- }
+ //
+ // Graphics Output Protocol is installed
+ // on virtual handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mConOut.VirtualHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &mConOut.GraphicsOutput,
+ NULL
+ );
}
//
@@ -3353,10 +3145,6 @@ ConSplitterTextOutDeleteDevice (
TextOutList = Private->TextOutList;
while (Index >= 0) {
if (TextOutList->TextOut == TextOut) {
- if (TextOutList->UgaDraw != NULL) {
- Private->CurrentNumberOfUgaDraw--;
- }
-
if (TextOutList->GraphicsOutput != NULL) {
Private->CurrentNumberOfGraphicsOutput--;
}
@@ -3377,33 +3165,16 @@ ConSplitterTextOutDeleteDevice (
return EFI_NOT_FOUND;
}
- if ((Private->CurrentNumberOfGraphicsOutput == 0) && (Private->CurrentNumberOfUgaDraw == 0)) {
+ if ((Private->CurrentNumberOfGraphicsOutput == 0)) {
//
- // If there is not any physical GOP and UGA device in system,
- // Consplitter GOP or UGA protocol will be uninstalled
+ // If there is not any physical GOP in system,
+ // Consplitter GOP protocol will be uninstalled
//
- if (!FeaturePcdGet (PcdConOutGopSupport)) {
- Status = gBS->UninstallProtocolInterface (
- Private->VirtualHandle,
- &gEfiUgaDrawProtocolGuid,
- &Private->UgaDraw
- );
- } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {
- Status = gBS->UninstallProtocolInterface (
- Private->VirtualHandle,
- &gEfiGraphicsOutputProtocolGuid,
- &Private->GraphicsOutput
- );
- } else {
- Status = gBS->UninstallMultipleProtocolInterfaces (
- Private->VirtualHandle,
- &gEfiUgaDrawProtocolGuid,
- &Private->UgaDraw,
- &gEfiGraphicsOutputProtocolGuid,
- &Private->GraphicsOutput,
- NULL
- );
- }
+ Status = gBS->UninstallProtocolInterface (
+ Private->VirtualHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ &Private->GraphicsOutput
+ );
}
if (CurrentNumOfConsoles == 0) {
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
index 354107c..f6d90d5 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
@@ -21,7 +21,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/SimpleTextIn.h>
#include <Protocol/SimpleTextInEx.h>
#include <Protocol/GraphicsOutput.h>
-#include <Protocol/UgaDraw.h>
#include <Guid/ConsoleInDevice.h>
#include <Guid/StandardErrorDevice.h>
@@ -182,7 +181,6 @@ typedef struct {
typedef struct {
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;
} TEXT_OUT_AND_GOP_DATA;
@@ -195,16 +193,9 @@ typedef struct {
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL TextOut;
EFI_SIMPLE_TEXT_OUTPUT_MODE TextOutMode;
- EFI_UGA_DRAW_PROTOCOL UgaDraw;
- UINT32 UgaHorizontalResolution;
- UINT32 UgaVerticalResolution;
- UINT32 UgaColorDepth;
- UINT32 UgaRefreshRate;
-
EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GraphicsOutputModeBuffer;
UINTN CurrentNumberOfGraphicsOutput;
- UINTN CurrentNumberOfUgaDraw;
UINTN CurrentNumberOfConsoles;
TEXT_OUT_AND_GOP_DATA *TextOutList;
@@ -230,13 +221,6 @@ typedef struct {
TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \
)
-#define UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \
- CR ((a), \
- TEXT_OUT_SPLITTER_PRIVATE_DATA, \
- UgaDraw, \
- TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \
- )
-
#define CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \
CR ((a), \
TEXT_OUT_SPLITTER_PRIVATE_DATA, \
@@ -254,7 +238,7 @@ typedef struct {
Installs driver module protocols and. Creates virtual device handles for ConIn,
ConOut, and StdErr. Installs Simple Text In protocol, Simple Text In Ex protocol,
Simple Pointer protocol, Absolute Pointer protocol on those virtual handlers.
- Installs Graphics Output protocol and/or UGA Draw protocol if needed.
+ Installs Graphics Output protocol if needed.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@@ -1202,7 +1186,6 @@ ConSplitterSimplePointerDeleteDevice (
@param Private Text Out Splitter pointer.
@param TextOut Simple Text Output protocol pointer.
@param GraphicsOutput Graphics Output protocol pointer.
- @param UgaDraw UGA Draw protocol pointer.
@retval EFI_SUCCESS Text Output Device added successfully.
@retval EFI_OUT_OF_RESOURCES Could not grow the buffer size.
@@ -1212,8 +1195,7 @@ EFI_STATUS
ConSplitterTextOutAddDevice (
IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private,
IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut,
- IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput,
- IN EFI_UGA_DRAW_PROTOCOL *UgaDraw
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput
);
/**
@@ -1858,118 +1840,6 @@ ConSplitterGraphicsOutputBlt (
);
/**
- Return the current video mode information.
-
- @param This The EFI_UGA_DRAW_PROTOCOL instance.
- @param HorizontalResolution The size of video screen in pixels in the X dimension.
- @param VerticalResolution The size of video screen in pixels in the Y dimension.
- @param ColorDepth Number of bits per pixel, currently defined to be 32.
- @param RefreshRate The refresh rate of the monitor in Hertz.
-
- @retval EFI_SUCCESS Mode information returned.
- @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
- @retval EFI_INVALID_PARAMETER One of the input args was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterUgaDrawGetMode (
- IN EFI_UGA_DRAW_PROTOCOL *This,
- OUT UINT32 *HorizontalResolution,
- OUT UINT32 *VerticalResolution,
- OUT UINT32 *ColorDepth,
- OUT UINT32 *RefreshRate
- );
-
-/**
- Set the current video mode information.
-
- @param This The EFI_UGA_DRAW_PROTOCOL instance.
- @param HorizontalResolution The size of video screen in pixels in the X dimension.
- @param VerticalResolution The size of video screen in pixels in the Y dimension.
- @param ColorDepth Number of bits per pixel, currently defined to be 32.
- @param RefreshRate The refresh rate of the monitor in Hertz.
-
- @retval EFI_SUCCESS Mode information returned.
- @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
- @retval EFI_OUT_OF_RESOURCES Out of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterUgaDrawSetMode (
- IN EFI_UGA_DRAW_PROTOCOL *This,
- IN UINT32 HorizontalResolution,
- IN UINT32 VerticalResolution,
- IN UINT32 ColorDepth,
- IN UINT32 RefreshRate
- );
-
-/**
- Blt a rectangle of pixels on the graphics screen.
-
- The following table defines actions for BltOperations.
-
- EfiUgaVideoFill:
- Write data from the BltBuffer pixel (SourceX, SourceY)
- directly to every pixel of the video display rectangle
- (DestinationX, DestinationY)
- (DestinationX + Width, DestinationY + Height).
- Only one pixel will be used from the BltBuffer. Delta is NOT used.
- EfiUgaVideoToBltBuffer:
- Read data from the video display rectangle
- (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
- the BltBuffer rectangle (DestinationX, DestinationY )
- (DestinationX + Width, DestinationY + Height). If DestinationX or
- DestinationY is not zero then Delta must be set to the length in bytes
- of a row in the BltBuffer.
- EfiUgaBltBufferToVideo:
- Write data from the BltBuffer rectangle
- (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
- video display rectangle (DestinationX, DestinationY)
- (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
- not zero then Delta must be set to the length in bytes of a row in the
- BltBuffer.
- EfiUgaVideoToVideo:
- Copy from the video display rectangle
- (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
- to the video display rectangle (DestinationX, DestinationY)
- (DestinationX + Width, DestinationY + Height).
- The BltBuffer and Delta are not used in this mode.
-
- @param This Protocol instance pointer.
- @param BltBuffer Buffer containing data to blit into video buffer. This
- buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
- @param BltOperation Operation to perform on BlitBuffer and video memory
- @param SourceX X coordinate of source for the BltBuffer.
- @param SourceY Y coordinate of source for the BltBuffer.
- @param DestinationX X coordinate of destination for the BltBuffer.
- @param DestinationY Y coordinate of destination for the BltBuffer.
- @param Width Width of rectangle in BltBuffer in pixels.
- @param Height Hight of rectangle in BltBuffer in pixels.
- @param Delta OPTIONAL
-
- @retval EFI_SUCCESS The Blt operation completed.
- @retval EFI_INVALID_PARAMETER BltOperation is not valid.
- @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterUgaDrawBlt (
- IN EFI_UGA_DRAW_PROTOCOL *This,
- IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,
- IN EFI_UGA_BLT_OPERATION BltOperation,
- IN UINTN SourceX,
- IN UINTN SourceY,
- IN UINTN DestinationX,
- IN UINTN DestinationY,
- IN UINTN Width,
- IN UINTN Height,
- IN UINTN Delta OPTIONAL
- );
-
-/**
Sets the output device(s) to a specified mode.
@param Private Text Out Splitter pointer.
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
index 9aa1dad..156757a 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
@@ -3,12 +3,9 @@
#
# This driver acts as a virtual console, takes over the console I/O control from selected
# standard console devices, and transmits console I/O to related console device drivers.
-# Consplitter could install Graphics Output protocol and/or UGA Draw protocol in system
-# table according PCD settings(PcdConOutGopSupport, and PcdConOutUgaSupport). It always
-# consumes Graphics Output protocol which is produced by display device, and consumes UGA Draw
-# protocol which is produced by display device according to PcdUgaConsumeSupport value.
-# Note: If only UGA Draw protocol is installed in system, PcdUgaConsumeSupport should be
-# set to TRUE.
+# Consplitter could install Graphics Output protocol in system
+# table according PCD settings(PcdConOutGopSupport). It always
+# consumes Graphics Output protocol which is produced by display device
#
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
#
@@ -92,14 +89,9 @@
## SOMETIMES_PRODUCES
## SOMETIMES_CONSUMES
gEfiGraphicsOutputProtocolGuid
- ## SOMETIMES_PRODUCES
- ## SOMETIMES_CONSUMES
- gEfiUgaDrawProtocolGuid
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport ## CONSUMES
- gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES
[Pcd]
## SOMETIMES_PRODUCES
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.uni b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.uni
index 13c25b2..903c505 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.uni
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.uni
@@ -3,12 +3,9 @@
//
// This driver acts as a virtual console, takes over the console I/O control from selected
// standard console devices, and transmits console I/O to related console device drivers.
-// Consplitter could install Graphics Output protocol and/or UGA Draw protocol in system
-// table according PCD settings(PcdConOutGopSupport, and PcdConOutUgaSupport). It always
-// consumes Graphics Output protocol which is produced by display device, and consumes UGA Draw
-// protocol which is produced by display device according to PcdUgaConsumeSupport value.
-// Note: If only UGA Draw protocol is installed in system, PcdUgaConsumeSupport should be
-// set to TRUE.
+// Consplitter could install Graphics Output protocol in system
+// table according PCD settings(PcdConOutGopSupport). It always
+// consumes Graphics Output protocol which is produced by display device
//
// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
//
@@ -19,5 +16,5 @@
#string STR_MODULE_ABSTRACT #language en-US "Provides multi console support"
-#string STR_MODULE_DESCRIPTION #language en-US "This driver acts as a virtual console, takes over the console I/O control from selected standard console devices, and transmits console I/O to related console device drivers. Consplitter could install Graphics Output protocol and/or UGA Draw protocol in system table according PCD settings(PcdConOutGopSupport, and PcdConOutUgaSupport). It always consumes Graphics Output protocol, which is produced by display device, and consumes UGA Draw protocol, which is produced by display device according to PcdUgaConsumeSupport value. Note: If only UGA Draw protocol is installed in system, PcdUgaConsumeSupport should be set to TRUE."
+#string STR_MODULE_DESCRIPTION #language en-US "This driver acts as a virtual console, takes over the console I/O control from selected standard console devices, and transmits console I/O to related console device drivers. Consplitter could install Graphics Output protocol in system table according PCD settings(PcdConOutGopSupport). It always consumes Graphics Output protocol, which is produced by display device."
diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
index 64ad567..8353f0b 100644
--- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
+++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
@@ -117,7 +117,6 @@ ConSplitterGraphicsOutputSetMode (
UINTN NumberIndex;
UINTN SizeOfInfo;
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
if (ModeNumber >= This->Mode->MaxMode) {
return EFI_UNSUPPORTED;
@@ -157,20 +156,6 @@ ConSplitterGraphicsOutputSetMode (
if (EFI_ERROR (Status)) {
ReturnStatus = Status;
}
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- UgaDraw = Private->TextOutList[Index].UgaDraw;
- if (UgaDraw != NULL) {
- Status = UgaDraw->SetMode (
- UgaDraw,
- Mode->HorizontalResolution,
- Mode->VerticalResolution,
- 32,
- 60
- );
- if (EFI_ERROR (Status)) {
- ReturnStatus = Status;
- }
- }
}
}
@@ -261,7 +246,6 @@ ConSplitterGraphicsOutputBlt (
TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
UINTN Index;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
if ((This == NULL) || (((UINTN)BltOperation) >= EfiGraphicsOutputBltOperationMax)) {
return EFI_INVALID_PARAMETER;
@@ -298,298 +282,6 @@ ConSplitterGraphicsOutputBlt (
return EFI_SUCCESS;
}
}
-
- UgaDraw = Private->TextOutList[Index].UgaDraw;
- if ((UgaDraw != NULL) && FeaturePcdGet (PcdUgaConsumeSupport)) {
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)BltBuffer,
- (EFI_UGA_BLT_OPERATION)BltOperation,
- SourceX,
- SourceY,
- DestinationX,
- DestinationY,
- Width,
- Height,
- Delta
- );
- if (EFI_ERROR (Status)) {
- ReturnStatus = Status;
- } else if (BltOperation == EfiBltVideoToBltBuffer) {
- //
- // Only need to read the data into buffer one time
- //
- return EFI_SUCCESS;
- }
- }
- }
-
- return ReturnStatus;
-}
-
-/**
- Return the current video mode information.
-
- @param This The EFI_UGA_DRAW_PROTOCOL instance.
- @param HorizontalResolution The size of video screen in pixels in the X dimension.
- @param VerticalResolution The size of video screen in pixels in the Y dimension.
- @param ColorDepth Number of bits per pixel, currently defined to be 32.
- @param RefreshRate The refresh rate of the monitor in Hertz.
-
- @retval EFI_SUCCESS Mode information returned.
- @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
- @retval EFI_INVALID_PARAMETER One of the input args was NULL.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterUgaDrawGetMode (
- IN EFI_UGA_DRAW_PROTOCOL *This,
- OUT UINT32 *HorizontalResolution,
- OUT UINT32 *VerticalResolution,
- OUT UINT32 *ColorDepth,
- OUT UINT32 *RefreshRate
- )
-{
- TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
-
- if ((HorizontalResolution == NULL) ||
- (VerticalResolution == NULL) ||
- (RefreshRate == NULL) ||
- (ColorDepth == NULL))
- {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // retrieve private data
- //
- Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
-
- *HorizontalResolution = Private->UgaHorizontalResolution;
- *VerticalResolution = Private->UgaVerticalResolution;
- *ColorDepth = Private->UgaColorDepth;
- *RefreshRate = Private->UgaRefreshRate;
-
- return EFI_SUCCESS;
-}
-
-/**
- Set the current video mode information.
-
- @param This The EFI_UGA_DRAW_PROTOCOL instance.
- @param HorizontalResolution The size of video screen in pixels in the X dimension.
- @param VerticalResolution The size of video screen in pixels in the Y dimension.
- @param ColorDepth Number of bits per pixel, currently defined to be 32.
- @param RefreshRate The refresh rate of the monitor in Hertz.
-
- @retval EFI_SUCCESS Mode information returned.
- @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
- @retval EFI_OUT_OF_RESOURCES Out of resources.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterUgaDrawSetMode (
- IN EFI_UGA_DRAW_PROTOCOL *This,
- IN UINT32 HorizontalResolution,
- IN UINT32 VerticalResolution,
- IN UINT32 ColorDepth,
- IN UINT32 RefreshRate
- )
-{
- EFI_STATUS Status;
- TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
- UINTN Index;
- EFI_STATUS ReturnStatus;
- EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- UINTN NumberIndex;
- UINTN SizeOfInfo;
- EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
-
- Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
-
- ReturnStatus = EFI_SUCCESS;
-
- //
- // Update the Mode data
- //
- Private->UgaHorizontalResolution = HorizontalResolution;
- Private->UgaVerticalResolution = VerticalResolution;
- Private->UgaColorDepth = ColorDepth;
- Private->UgaRefreshRate = RefreshRate;
-
- //
- // return the worst status met
- //
- for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
- GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
- if (GraphicsOutput != NULL) {
- //
- // Find corresponding ModeNumber of this GraphicsOutput instance
- //
- for (NumberIndex = 0; NumberIndex < GraphicsOutput->Mode->MaxMode; NumberIndex++) {
- Status = GraphicsOutput->QueryMode (GraphicsOutput, (UINT32)NumberIndex, &SizeOfInfo, &Info);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- if ((Info->HorizontalResolution == HorizontalResolution) && (Info->VerticalResolution == VerticalResolution)) {
- FreePool (Info);
- break;
- }
-
- FreePool (Info);
- }
-
- Status = GraphicsOutput->SetMode (GraphicsOutput, (UINT32)NumberIndex);
- if (EFI_ERROR (Status)) {
- ReturnStatus = Status;
- }
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- UgaDraw = Private->TextOutList[Index].UgaDraw;
- if (UgaDraw != NULL) {
- Status = UgaDraw->SetMode (
- UgaDraw,
- HorizontalResolution,
- VerticalResolution,
- ColorDepth,
- RefreshRate
- );
- if (EFI_ERROR (Status)) {
- ReturnStatus = Status;
- }
- }
- }
- }
-
- return ReturnStatus;
-}
-
-/**
- Blt a rectangle of pixels on the graphics screen.
-
- The following table defines actions for BltOperations.
-
- EfiUgaVideoFill:
- Write data from the BltBuffer pixel (SourceX, SourceY)
- directly to every pixel of the video display rectangle
- (DestinationX, DestinationY)
- (DestinationX + Width, DestinationY + Height).
- Only one pixel will be used from the BltBuffer. Delta is NOT used.
- EfiUgaVideoToBltBuffer:
- Read data from the video display rectangle
- (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in
- the BltBuffer rectangle (DestinationX, DestinationY )
- (DestinationX + Width, DestinationY + Height). If DestinationX or
- DestinationY is not zero then Delta must be set to the length in bytes
- of a row in the BltBuffer.
- EfiUgaBltBufferToVideo:
- Write data from the BltBuffer rectangle
- (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the
- video display rectangle (DestinationX, DestinationY)
- (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is
- not zero then Delta must be set to the length in bytes of a row in the
- BltBuffer.
- EfiUgaVideoToVideo:
- Copy from the video display rectangle
- (SourceX, SourceY) (SourceX + Width, SourceY + Height) .
- to the video display rectangle (DestinationX, DestinationY)
- (DestinationX + Width, DestinationY + Height).
- The BltBuffer and Delta are not used in this mode.
-
- @param This Protocol instance pointer.
- @param BltBuffer Buffer containing data to blit into video buffer. This
- buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL)
- @param BltOperation Operation to perform on BlitBuffer and video memory
- @param SourceX X coordinate of source for the BltBuffer.
- @param SourceY Y coordinate of source for the BltBuffer.
- @param DestinationX X coordinate of destination for the BltBuffer.
- @param DestinationY Y coordinate of destination for the BltBuffer.
- @param Width Width of rectangle in BltBuffer in pixels.
- @param Height Hight of rectangle in BltBuffer in pixels.
- @param Delta OPTIONAL
-
- @retval EFI_SUCCESS The Blt operation completed.
- @retval EFI_INVALID_PARAMETER BltOperation is not valid.
- @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.
-
-**/
-EFI_STATUS
-EFIAPI
-ConSplitterUgaDrawBlt (
- IN EFI_UGA_DRAW_PROTOCOL *This,
- IN EFI_UGA_PIXEL *BltBuffer OPTIONAL,
- IN EFI_UGA_BLT_OPERATION BltOperation,
- IN UINTN SourceX,
- IN UINTN SourceY,
- IN UINTN DestinationX,
- IN UINTN DestinationY,
- IN UINTN Width,
- IN UINTN Height,
- IN UINTN Delta OPTIONAL
- )
-{
- EFI_STATUS Status;
- TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;
- UINTN Index;
- EFI_STATUS ReturnStatus;
- EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
-
- Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This);
-
- ReturnStatus = EFI_SUCCESS;
- //
- // return the worst status met
- //
- for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {
- GraphicsOutput = Private->TextOutList[Index].GraphicsOutput;
- if (GraphicsOutput != NULL) {
- Status = GraphicsOutput->Blt (
- GraphicsOutput,
- (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)BltBuffer,
- (EFI_GRAPHICS_OUTPUT_BLT_OPERATION)BltOperation,
- SourceX,
- SourceY,
- DestinationX,
- DestinationY,
- Width,
- Height,
- Delta
- );
- if (EFI_ERROR (Status)) {
- ReturnStatus = Status;
- } else if (BltOperation == EfiUgaVideoToBltBuffer) {
- //
- // Only need to read the data into buffer one time
- //
- return EFI_SUCCESS;
- }
- }
-
- if ((Private->TextOutList[Index].UgaDraw != NULL) && FeaturePcdGet (PcdUgaConsumeSupport)) {
- Status = Private->TextOutList[Index].UgaDraw->Blt (
- Private->TextOutList[Index].UgaDraw,
- BltBuffer,
- BltOperation,
- SourceX,
- SourceY,
- DestinationX,
- DestinationY,
- Width,
- Height,
- Delta
- );
- if (EFI_ERROR (Status)) {
- ReturnStatus = Status;
- } else if (BltOperation == EfiUgaVideoToBltBuffer) {
- //
- // Only need to read the data into buffer one time
- //
- return EFI_SUCCESS;
- }
- }
}
return ReturnStatus;
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
index b895daf..facb813 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
@@ -14,7 +14,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = {
GRAPHICS_CONSOLE_DEV_SIGNATURE,
(EFI_GRAPHICS_OUTPUT_PROTOCOL *)NULL,
- (EFI_UGA_DRAW_PROTOCOL *)NULL,
{
GraphicsConsoleConOutReset,
GraphicsConsoleConOutOutputString,
@@ -104,9 +103,8 @@ EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = {
/**
Test to see if Graphics Console could be supported on the Controller.
- Graphics Console could be supported if Graphics Output Protocol or UGA Draw
- Protocol exists on the Controller. (UGA Draw Protocol could be skipped
- if PcdUgaConsumeSupport is set to FALSE.)
+ Graphics Console could be supported if Graphics Output Protocol
+ exists on the Controller.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@@ -127,11 +125,9 @@ GraphicsConsoleControllerDriverSupported (
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
GraphicsOutput = NULL;
- UgaDraw = NULL;
//
// Open the IO Abstraction(s) needed to perform the supported test
//
@@ -143,21 +139,6 @@ GraphicsConsoleControllerDriverSupported (
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
-
- if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
- //
- // Open Graphics Output Protocol failed, try to open UGA Draw Protocol
- //
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUgaDrawProtocolGuid,
- (VOID **)&UgaDraw,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- }
-
if (EFI_ERROR (Status)) {
return Status;
}
@@ -202,13 +183,6 @@ Error:
This->DriverBindingHandle,
Controller
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- gBS->CloseProtocol (
- Controller,
- &gEfiUgaDrawProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
}
return Status;
@@ -369,9 +343,8 @@ InitializeGraphicsConsoleTextMode (
}
/**
- Start this driver on Controller by opening Graphics Output protocol or
- UGA Draw protocol, and installing Simple Text Out protocol on Controller.
- (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
+ Start this driver on Controller by opening Graphics Output protocol
+ and installing Simple Text Out protocol on Controller.
@param This Protocol instance pointer.
@param Controller Handle of device to bind driver to
@@ -394,8 +367,6 @@ GraphicsConsoleControllerDriverStart (
GRAPHICS_CONSOLE_DEV *Private;
UINT32 HorizontalResolution;
UINT32 VerticalResolution;
- UINT32 ColorDepth;
- UINT32 RefreshRate;
UINT32 ModeIndex;
UINTN MaxMode;
UINT32 ModeNumber;
@@ -432,18 +403,6 @@ GraphicsConsoleControllerDriverStart (
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
-
- if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {
- Status = gBS->OpenProtocol (
- Controller,
- &gEfiUgaDrawProtocolGuid,
- (VOID **)&Private->UgaDraw,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- }
-
if (EFI_ERROR (Status)) {
goto Error;
}
@@ -534,43 +493,6 @@ GraphicsConsoleControllerDriverStart (
goto Error;
}
}
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- //
- // At first try to set user-defined resolution
- //
- ColorDepth = 32;
- RefreshRate = 60;
- Status = Private->UgaDraw->SetMode (
- Private->UgaDraw,
- HorizontalResolution,
- VerticalResolution,
- ColorDepth,
- RefreshRate
- );
- if (EFI_ERROR (Status)) {
- //
- // Try to set 800*600 which is required by UEFI/EFI spec
- //
- Status = Private->UgaDraw->SetMode (
- Private->UgaDraw,
- 800,
- 600,
- ColorDepth,
- RefreshRate
- );
- if (EFI_ERROR (Status)) {
- Status = Private->UgaDraw->GetMode (
- Private->UgaDraw,
- &HorizontalResolution,
- &VerticalResolution,
- &ColorDepth,
- &RefreshRate
- );
- if (EFI_ERROR (Status)) {
- goto Error;
- }
- }
- }
}
DEBUG ((DEBUG_INFO, "GraphicsConsole video resolution %d x %d\n", HorizontalResolution, VerticalResolution));
@@ -638,7 +560,7 @@ GraphicsConsoleControllerDriverStart (
Error:
if (EFI_ERROR (Status)) {
//
- // Close the GOP and UGA Draw Protocol
+ // Close the GOP
//
if (Private->GraphicsOutput != NULL) {
gBS->CloseProtocol (
@@ -647,13 +569,6 @@ Error:
This->DriverBindingHandle,
Controller
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- gBS->CloseProtocol (
- Controller,
- &gEfiUgaDrawProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
}
if (Private->LineBuffer != NULL) {
@@ -675,9 +590,7 @@ Error:
/**
Stop this driver on Controller by removing Simple Text Out protocol
- and closing the Graphics Output Protocol or UGA Draw protocol on Controller.
- (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
-
+ and closing the Graphics Output Protocol on Controller.
@param This Protocol instance pointer.
@param Controller Handle of device to stop driver on
@@ -726,7 +639,7 @@ GraphicsConsoleControllerDriverStop (
if (!EFI_ERROR (Status)) {
//
- // Close the GOP or UGA IO Protocol
+ // Close the GOP Protocol
//
if (Private->GraphicsOutput != NULL) {
gBS->CloseProtocol (
@@ -735,13 +648,6 @@ GraphicsConsoleControllerDriverStop (
This->DriverBindingHandle,
Controller
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- gBS->CloseProtocol (
- Controller,
- &gEfiUgaDrawProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
}
if (Private->LineBuffer != NULL) {
@@ -933,7 +839,6 @@ GraphicsConsoleConOutOutputString (
{
GRAPHICS_CONSOLE_DEV *Private;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
INTN Mode;
UINTN MaxColumn;
UINTN MaxRow;
@@ -967,7 +872,6 @@ GraphicsConsoleConOutOutputString (
Mode = This->Mode->Mode;
Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
GraphicsOutput = Private->GraphicsOutput;
- UgaDraw = Private->UgaDraw;
MaxColumn = Private->ModeData[Mode].Columns;
MaxRow = Private->ModeData[Mode].Rows;
@@ -1055,38 +959,6 @@ GraphicsConsoleConOutOutputString (
EFI_GLYPH_HEIGHT,
Delta
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- //
- // Scroll Screen Up One Row
- //
- UgaDraw->Blt (
- UgaDraw,
- NULL,
- EfiUgaVideoToVideo,
- DeltaX,
- DeltaY + EFI_GLYPH_HEIGHT,
- DeltaX,
- DeltaY,
- Width,
- Height,
- Delta
- );
-
- //
- // Print Blank Line at last line
- //
- UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)(UINTN)&Background,
- EfiUgaVideoFill,
- 0,
- 0,
- DeltaX,
- DeltaY + Height,
- Width,
- EFI_GLYPH_HEIGHT,
- Delta
- );
}
} else {
This->Mode->CursorRow++;
@@ -1320,19 +1192,13 @@ GraphicsConsoleConOutSetMode (
GRAPHICS_CONSOLE_DEV *Private;
GRAPHICS_CONSOLE_MODE_DATA *ModeData;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *NewLineBuffer;
- UINT32 HorizontalResolution;
- UINT32 VerticalResolution;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
- UINT32 ColorDepth;
- UINT32 RefreshRate;
EFI_TPL OldTpl;
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
GraphicsOutput = Private->GraphicsOutput;
- UgaDraw = Private->UgaDraw;
//
// Make sure the requested mode number is supported
@@ -1366,7 +1232,7 @@ GraphicsConsoleConOutSetMode (
}
//
- // Otherwise, the size of the text console and/or the GOP/UGA mode will be changed,
+ // Otherwise, the size of the text console and/or the GOP mode will be changed,
// so erase the cursor, and free the LineBuffer for the current mode
//
FlushCursor (This);
@@ -1422,51 +1288,6 @@ GraphicsConsoleConOutSetMode (
0
);
}
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- //
- // Get the current UGA Draw mode information
- //
- Status = UgaDraw->GetMode (
- UgaDraw,
- &HorizontalResolution,
- &VerticalResolution,
- &ColorDepth,
- &RefreshRate
- );
- if (EFI_ERROR (Status) || (HorizontalResolution != ModeData->GopWidth) || (VerticalResolution != ModeData->GopHeight)) {
- //
- // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new graphics mode
- //
- Status = UgaDraw->SetMode (
- UgaDraw,
- ModeData->GopWidth,
- ModeData->GopHeight,
- 32,
- 60
- );
- if (EFI_ERROR (Status)) {
- //
- // The mode set operation failed
- //
- goto Done;
- }
- } else {
- //
- // The current graphics mode is correct, so simply clear the entire display
- //
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)(UINTN)&mGraphicsEfiColors[0],
- EfiUgaVideoFill,
- 0,
- 0,
- 0,
- 0,
- ModeData->GopWidth,
- ModeData->GopHeight,
- 0
- );
- }
}
//
@@ -1558,7 +1379,6 @@ GraphicsConsoleConOutClearScreen (
GRAPHICS_CONSOLE_DEV *Private;
GRAPHICS_CONSOLE_MODE_DATA *ModeData;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
EFI_TPL OldTpl;
@@ -1574,7 +1394,6 @@ GraphicsConsoleConOutClearScreen (
Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
GraphicsOutput = Private->GraphicsOutput;
- UgaDraw = Private->UgaDraw;
ModeData = &(Private->ModeData[This->Mode->Mode]);
GetTextColors (This, &Foreground, &Background);
@@ -1591,19 +1410,6 @@ GraphicsConsoleConOutClearScreen (
ModeData->GopHeight,
0
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)(UINTN)&Background,
- EfiUgaVideoFill,
- 0,
- 0,
- 0,
- 0,
- ModeData->GopWidth,
- ModeData->GopHeight,
- 0
- );
} else {
Status = EFI_UNSUPPORTED;
}
@@ -1764,7 +1570,7 @@ GetTextColors (
@param Count The count of Unicode string.
@retval EFI_OUT_OF_RESOURCES If no memory resource to use.
- @retval EFI_UNSUPPORTED If no Graphics Output protocol and UGA Draw
+ @retval EFI_UNSUPPORTED If no Graphics Output protocol
protocol exist.
@retval EFI_SUCCESS Drawing Unicode string implemented successfully.
@@ -1781,9 +1587,6 @@ DrawUnicodeWeightAtCursorN (
EFI_IMAGE_OUTPUT *Blt;
EFI_STRING String;
EFI_FONT_DISPLAY_INFO *FontInfo;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
- EFI_HII_ROW_INFO *RowInfoArray;
- UINTN RowInfoArraySize;
Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
Blt = (EFI_IMAGE_OUTPUT *)AllocateZeroPool (sizeof (EFI_IMAGE_OUTPUT));
@@ -1835,63 +1638,6 @@ DrawUnicodeWeightAtCursorN (
NULL,
NULL
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- //
- // If Graphics Output protocol cannot be found and PcdUgaConsumeSupport enabled,
- // using UGA Draw protocol to draw.
- //
- ASSERT (Private->UgaDraw != NULL);
-
- UgaDraw = Private->UgaDraw;
-
- Blt->Image.Bitmap = AllocateZeroPool (Blt->Width * Blt->Height * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
- if (Blt->Image.Bitmap == NULL) {
- FreePool (Blt);
- FreePool (String);
- return EFI_OUT_OF_RESOURCES;
- }
-
- RowInfoArray = NULL;
- //
- // StringToImage only support blt'ing image to device using GOP protocol. If GOP is not supported in this platform,
- // we ask StringToImage to print the string to blt buffer, then blt to device using UgaDraw.
- //
- Status = mHiiFont->StringToImage (
- mHiiFont,
- EFI_HII_IGNORE_IF_NO_GLYPH | EFI_HII_IGNORE_LINE_BREAK,
- String,
- FontInfo,
- &Blt,
- This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
- This->Mode->CursorRow * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
- &RowInfoArray,
- &RowInfoArraySize,
- NULL
- );
-
- if (!EFI_ERROR (Status)) {
- //
- // Line breaks are handled by caller of DrawUnicodeWeightAtCursorN, so the updated parameter RowInfoArraySize by StringToImage will
- // always be 1 or 0 (if there is no valid Unicode Char can be printed). ASSERT here to make sure.
- //
- ASSERT (RowInfoArraySize <= 1);
-
- Status = UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)Blt->Image.Bitmap,
- EfiUgaBltBufferToVideo,
- This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
- (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
- This->Mode->CursorColumn * EFI_GLYPH_WIDTH + Private->ModeData[This->Mode->Mode].DeltaX,
- (This->Mode->CursorRow) * EFI_GLYPH_HEIGHT + Private->ModeData[This->Mode->Mode].DeltaY,
- RowInfoArray[0].LineWidth,
- RowInfoArray[0].LineHeight,
- Blt->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
- );
- }
-
- FreePool (RowInfoArray);
- FreePool (Blt->Image.Bitmap);
} else {
Status = EFI_UNSUPPORTED;
}
@@ -1934,7 +1680,6 @@ FlushCursor (
INTN GlyphX;
INTN GlyphY;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Foreground;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Background;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION BltChar[EFI_GLYPH_HEIGHT][EFI_GLYPH_WIDTH];
@@ -1949,7 +1694,6 @@ FlushCursor (
Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This);
GraphicsOutput = Private->GraphicsOutput;
- UgaDraw = Private->UgaDraw;
//
// In this driver, only narrow character was supported.
@@ -1972,19 +1716,6 @@ FlushCursor (
EFI_GLYPH_HEIGHT,
EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)(UINTN)BltChar,
- EfiUgaVideoToBltBuffer,
- GlyphX,
- GlyphY,
- 0,
- 0,
- EFI_GLYPH_WIDTH,
- EFI_GLYPH_HEIGHT,
- EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
- );
}
GetTextColors (This, &Foreground.Pixel, &Background.Pixel);
@@ -2013,19 +1744,6 @@ FlushCursor (
EFI_GLYPH_HEIGHT,
EFI_GLYPH_WIDTH * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
);
- } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {
- UgaDraw->Blt (
- UgaDraw,
- (EFI_UGA_PIXEL *)(UINTN)BltChar,
- EfiUgaBltBufferToVideo,
- 0,
- 0,
- GlyphX,
- GlyphY,
- EFI_GLYPH_WIDTH,
- EFI_GLYPH_HEIGHT,
- EFI_GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL)
- );
}
return EFI_SUCCESS;
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
index e4abad4..e1a6b37 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
@@ -12,7 +12,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Uefi.h>
#include <Protocol/SimpleTextOut.h>
#include <Protocol/GraphicsOutput.h>
-#include <Protocol/UgaDraw.h>
#include <Protocol/DevicePath.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
@@ -59,7 +58,6 @@ typedef struct {
typedef struct {
UINTN Signature;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
- EFI_UGA_DRAW_PROTOCOL *UgaDraw;
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOutput;
EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode;
GRAPHICS_CONSOLE_MODE_DATA *ModeData;
@@ -417,9 +415,8 @@ GraphicsConsoleConOutEnableCursor (
/**
Test to see if Graphics Console could be supported on the Controller.
- Graphics Console could be supported if Graphics Output Protocol or UGADraw
- Protocol exists on the Controller. (UGA Draw Protocol could be skipped
- if PcdUgaConsumeSupport is set to FALSE.)
+ Graphics Console could be supported if Graphics Output Protocol
+ exists on the Controller.
@param This Protocol instance pointer.
@param Controller Handle of device to test.
@@ -439,9 +436,8 @@ GraphicsConsoleControllerDriverSupported (
);
/**
- Start this driver on Controller by opening Graphics Output protocol or
- UGA Draw protocol, and installing Simple Text Out protocol on Controller.
- (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
+ Start this driver on Controller by opening Graphics Output protocol
+ and installing Simple Text Out protocol on Controller.
@param This Protocol instance pointer.
@param Controller Handle of device to bind driver to
@@ -462,9 +458,7 @@ GraphicsConsoleControllerDriverStart (
/**
Stop this driver on Controller by removing Simple Text Out protocol
- and closing the Graphics Output Protocol or UGA Draw protocol on Controller.
- (UGA Draw protocol could be skipped if PcdUgaConsumeSupport is set to FALSE.)
-
+ and closing the Graphics Output Protocol on Controller.
@param This Protocol instance pointer.
@param Controller Handle of device to stop driver on
@@ -526,8 +520,7 @@ GetTextColors (
@param Count The count of Unicode string.
@retval EFI_OUT_OF_RESOURCES If no memory resource to use.
- @retval EFI_UNSUPPORTED If no Graphics Output protocol and UGA Draw
- protocol exist.
+ @retval EFI_UNSUPPORTED If no Graphics Output protocol exist.
@retval EFI_SUCCESS Drawing Unicode string implemented successfully.
**/
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
index bcfd306..975871b 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
@@ -2,7 +2,7 @@
# Console support on graphic devices.
#
# This driver will install Simple Text Output protocol by consuming Graphices Output
-# protocol or UGA Draw protocol on graphic devices.
+# protocol on graphic devices.
#
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -53,15 +53,11 @@
gEfiDevicePathProtocolGuid ## TO_START
gEfiSimpleTextOutProtocolGuid ## BY_START
gEfiGraphicsOutputProtocolGuid ## TO_START
- gEfiUgaDrawProtocolGuid ## TO_START
gEfiHiiFontProtocolGuid ## TO_START
## TO_START
## NOTIFY
gEfiHiiDatabaseProtocolGuid
-[FeaturePcd]
- gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport ## CONSUMES
-
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.uni b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.uni
index aec5d57..45dbb24 100644
--- a/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.uni
+++ b/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.uni
@@ -2,7 +2,7 @@
// Console support on graphic devices.
//
// This driver will install Simple Text Output protocol by consuming Graphices Output
-// protocol or UGA Draw protocol on graphic devices.
+// protocol on graphic devices.
//
// Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
//
@@ -14,5 +14,5 @@
#string STR_MODULE_ABSTRACT #language en-US "Console support on graphic devices"
#string STR_MODULE_DESCRIPTION #language en-US "This driver will install SimpleTextOutputProtocol by consuming GraphicesOutput\n"
- "Protocol or UgaDrawProtocol on graphics devices."
+ "Protocol on graphics devices."
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
index e2d779c..50f79f5 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.c
@@ -2,6 +2,7 @@
Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and
Simple Text Output Protocol upon Serial IO Protocol.
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -114,7 +115,10 @@ TERMINAL_DEV mTerminalDevTemplate = {
TERMINAL_CONSOLE_MODE_DATA mTerminalConsoleModeData[] = {
{ 80, 25 },
{ 80, 50 },
- { 100, 31 },
+ { 100, 31 }, // 800 x 600
+ { 128, 40 }, // 1024 x 768
+ { 160, 42 }, // 1280 x 800
+ { 240, 56 }, // 1920 x 1080
//
// New modes can be added here.
//
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
index 7581cda..66438be 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
@@ -1,6 +1,7 @@
/** @file
Header file for Terminal driver.
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -162,6 +163,8 @@ typedef union {
#define ROW_OFFSET 2
#define COLUMN_OFFSET 5
#define FW_BACK_OFFSET 2
+#define RESIZE_ROW_OFFSET 4
+#define RESIZE_COLUMN_OFFSET 8
typedef struct {
UINT16 Unicode;
@@ -1216,8 +1219,8 @@ AnsiRawDataToUnicode (
Putty function key map:
+=========+======+===========+=============+=============+=============+=========+
| | EFI | | | | | |
- | | Scan | | | Normal | | |
- | KEY | Code | VT100+ | Xterm R6 | VT400 | Linux | SCO |
+ | | Scan | VT100+ | | Normal | | |
+ | KEY | Code | VTUTF8 | Xterm R6 | VT400 | Linux | SCO |
+=========+======+===========+=============+=============+=============+=========+
| F1 | 0x0B | ESC O P | ESC O P | ESC [ 1 1 ~ | ESC [ [ A | ESC [ M |
| F2 | 0x0C | ESC O Q | ESC O Q | ESC [ 1 2 ~ | ESC [ [ B | ESC [ N |
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
index aafa65f..f1d0a34 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConIn.c
@@ -95,6 +95,13 @@ TerminalConInReset (
);
}
+ if (!EFI_ERROR (Status)) {
+ Status = TerminalDevice->SerialIo->SetControl (TerminalDevice->SerialIo, EFI_SERIAL_DATA_TERMINAL_READY|EFI_SERIAL_REQUEST_TO_SEND);
+ if (Status == EFI_UNSUPPORTED) {
+ Status = EFI_SUCCESS;
+ }
+ }
+
return Status;
}
@@ -1313,8 +1320,8 @@ UnicodeToEfiKeyFlushState (
Putty function key map:
+=========+======+===========+=============+=============+=============+=========+
| | EFI | | | | | |
- | | Scan | | | Normal | | |
- | KEY | Code | VT100+ | Xterm R6 | VT400 | Linux | SCO |
+ | | Scan | VT100+ | | Normal | | |
+ | KEY | Code | VTUTF8 | Xterm R6 | VT400 | Linux | SCO |
+=========+======+===========+=============+=============+=============+=========+
| F1 | 0x0B | ESC O P | ESC O P | ESC [ 1 1 ~ | ESC [ [ A | ESC [ M |
| F2 | 0x0C | ESC O Q | ESC O Q | ESC [ 1 2 ~ | ESC [ [ B | ESC [ N |
@@ -1391,7 +1398,8 @@ UnicodeToEfiKey (
if ((UnicodeChar == 'O') && ((TerminalDevice->TerminalType == TerminalTypeVt100) ||
(TerminalDevice->TerminalType == TerminalTypeTtyTerm) ||
(TerminalDevice->TerminalType == TerminalTypeXtermR6) ||
- (TerminalDevice->TerminalType == TerminalTypeVt100Plus)))
+ (TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
+ (TerminalDevice->TerminalType == TerminalTypeVtUtf8)))
{
TerminalDevice->InputState |= INPUT_STATE_O;
TerminalDevice->ResetState = RESET_STATE_DEFAULT;
@@ -1565,7 +1573,9 @@ UnicodeToEfiKey (
Key.ScanCode = SCAN_END;
break;
}
- } else if (TerminalDevice->TerminalType == TerminalTypeVt100Plus) {
+ } else if ((TerminalDevice->TerminalType == TerminalTypeVt100Plus) ||
+ (TerminalDevice->TerminalType == TerminalTypeVtUtf8))
+ {
switch (UnicodeChar) {
case 'P':
Key.ScanCode = SCAN_F1;
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
index 7809869..eb8658c 100644
--- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
+++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c
@@ -1,6 +1,7 @@
/** @file
Implementation for EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL protocol.
+Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.<BR>
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -74,6 +75,7 @@ UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = {
};
CHAR16 mSetModeString[] = { ESC, '[', '=', '3', 'h', 0 };
+CHAR16 mSetModeStringResize[] = { ESC, '[', '8', ';', '0', '0', '0', ';', '0', '0', '0', 't', '0', 0 };
CHAR16 mSetAttributeString[] = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 };
CHAR16 mClearScreenString[] = { ESC, '[', '2', 'J', 0 };
CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 };
@@ -453,7 +455,6 @@ TerminalConOutQueryMode (
Implements EFI_SIMPLE_TEXT_OUT.SetMode().
Set the terminal to a specified display mode.
- In this driver, we only support mode 0.
@param This Indicates the calling context.
@param ModeNumber The text mode to set.
@@ -473,9 +474,12 @@ TerminalConOutSetMode (
{
EFI_STATUS Status;
TERMINAL_DEV *TerminalDevice;
+ CHAR16 *String;
+ UINTN Columns;
+ UINTN Rows;
//
- // get Terminal device data structure pointer.
+ // Get Terminal device data structure pointer.
//
TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
@@ -484,6 +488,25 @@ TerminalConOutSetMode (
}
//
+ // Configure terminal string for the text mode to set.
+ //
+ if (ModeNumber == 0) {
+ String = mSetModeString;
+ } else {
+ Columns = TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns;
+ Rows = TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows;
+
+ mSetModeStringResize[RESIZE_ROW_OFFSET + 0] = (CHAR16)('0' + (Rows / 100));
+ mSetModeStringResize[RESIZE_ROW_OFFSET + 1] = (CHAR16)('0' + ((Rows - ((Rows / 100) * 100)) / 10));
+ mSetModeStringResize[RESIZE_ROW_OFFSET + 2] = (CHAR16)('0' + (Rows % 10));
+ mSetModeStringResize[RESIZE_COLUMN_OFFSET + 0] = (CHAR16)('0' + (Columns / 100));
+ mSetModeStringResize[RESIZE_COLUMN_OFFSET + 1] = (CHAR16)('0' + ((Columns - ((Columns / 100) * 100)) / 10));
+ mSetModeStringResize[RESIZE_COLUMN_OFFSET + 2] = (CHAR16)('0' + (Columns % 10));
+
+ String = mSetModeStringResize;
+ }
+
+ //
// Set the current mode
//
This->Mode->Mode = (INT32)ModeNumber;
@@ -491,7 +514,7 @@ TerminalConOutSetMode (
This->ClearScreen (This);
TerminalDevice->OutputEscChar = TRUE;
- Status = This->OutputString (This, mSetModeString);
+ Status = This->OutputString (This, String);
TerminalDevice->OutputEscChar = FALSE;
if (EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Universal/DebugServicePei/DebugServicePei.c b/MdeModulePkg/Universal/DebugServicePei/DebugServicePei.c
index b340727..cc3257e 100644
--- a/MdeModulePkg/Universal/DebugServicePei/DebugServicePei.c
+++ b/MdeModulePkg/Universal/DebugServicePei/DebugServicePei.c
@@ -78,7 +78,7 @@ PeiDebugAssert (
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
- @retval EFI_SUCESS The entry point of Debug Service PEIM executes successfully.
+ @retval EFI_SUCCESS The entry point of Debug Service PEIM executes successfully.
@retval Others Some error occurs during the execution of this function.
**/
diff --git a/MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c b/MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c
index 40fe74d..2291985 100644
--- a/MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c
+++ b/MdeModulePkg/Universal/DebugSupportDxe/Ia32/PlDebugSupport.c
@@ -262,17 +262,24 @@ InvalidateInstructionCache (
**/
VOID
InterruptDistrubutionHub (
- EFI_EXCEPTION_TYPE ExceptionType,
- EFI_SYSTEM_CONTEXT_IA32 *ContextRecord
+ IN EFI_EXCEPTION_TYPE ExceptionType,
+ IN EFI_SYSTEM_CONTEXT ContextRecord
)
{
- if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) {
- if (ExceptionType != SYSTEM_TIMER_VECTOR) {
- IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord);
- } else {
- OrigVector = IdtEntryTable[ExceptionType].OrigVector;
- IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord);
- }
+ EFI_EXCEPTION_CALLBACK ExceptionCallback;
+ EFI_PERIODIC_CALLBACK PeriodicCallback;
+
+ if (IdtEntryTable[ExceptionType].RegisteredCallback == NULL) {
+ return;
+ }
+
+ if (ExceptionType == SYSTEM_TIMER_VECTOR) {
+ OrigVector = IdtEntryTable[ExceptionType].OrigVector;
+ PeriodicCallback = (EFI_PERIODIC_CALLBACK)IdtEntryTable[ExceptionType].RegisteredCallback;
+ PeriodicCallback (ContextRecord);
+ } else {
+ ExceptionCallback = (EFI_EXCEPTION_CALLBACK)IdtEntryTable[ExceptionType].RegisteredCallback;
+ ExceptionCallback (ExceptionType, ContextRecord);
}
}
diff --git a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
index 38af39f..54b634a 100644
--- a/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
+++ b/MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIo.c
@@ -846,7 +846,8 @@ DiskIo2ReadWriteDisk (
LIST_ENTRY Subtasks;
DISK_IO_SUBTASK *Subtask;
DISK_IO2_TASK *Task;
- EFI_TPL OldTpl;
+ EFI_TPL SubtaskPerformTpl;
+ EFI_TPL SubtaskLockTpl;
BOOLEAN Blocking;
BOOLEAN SubtaskBlocking;
LIST_ENTRY *SubtasksPtr;
@@ -896,7 +897,7 @@ DiskIo2ReadWriteDisk (
ASSERT (!IsListEmpty (SubtasksPtr));
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+ SubtaskPerformTpl = gBS->RaiseTPL (TPL_CALLBACK);
for ( Link = GetFirstNode (SubtasksPtr), NextLink = GetNextNode (SubtasksPtr, Link)
; !IsNull (SubtasksPtr, Link)
; Link = NextLink, NextLink = GetNextNode (SubtasksPtr, NextLink)
@@ -977,7 +978,7 @@ DiskIo2ReadWriteDisk (
}
}
- gBS->RaiseTPL (TPL_NOTIFY);
+ SubtaskLockTpl = gBS->RaiseTPL (TPL_NOTIFY);
//
// Remove all the remaining subtasks when failure.
@@ -1012,7 +1013,8 @@ DiskIo2ReadWriteDisk (
FreePool (Task);
}
- gBS->RestoreTPL (OldTpl);
+ gBS->RestoreTPL (SubtaskLockTpl);
+ gBS->RestoreTPL (SubtaskPerformTpl);
return Status;
}
diff --git a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c
index 60cf3c8..2dac121 100644
--- a/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c
+++ b/MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskImpl.c
@@ -404,7 +404,8 @@ HiiCreateRamDisk (
);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- return EFI_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto ErrorExit;
}
}
@@ -431,7 +432,7 @@ HiiCreateRamDisk (
);
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
- return Status;
+ goto ErrorExit;
}
//
@@ -442,6 +443,10 @@ HiiCreateRamDisk (
PrivateData->CreateMethod = RamDiskCreateHii;
return EFI_SUCCESS;
+
+ErrorExit:
+ gBS->FreePool (StartingAddr);
+ return Status;
}
/**
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
index a7b7dc7..81020b2 100644
--- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
@@ -2014,8 +2014,8 @@ FindTopMenu (
/**
Record the highlight menu and top of screen menu info.
- @param Highlight The menu opton which is highlight.
- @param TopOfScreen The menu opton which is at the top of the form.
+ @param Highlight The menu option which is highlight.
+ @param TopOfScreen The menu option which is at the top of the form.
@param SkipValue The skip line info for the top of screen menu.
**/
@@ -2095,9 +2095,9 @@ UpdateHighlightMenuInfo (
}
/**
- Update attribut for this menu.
+ Update attribute for this menu.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@param Highlight Whether this menu will be highlight.
**/
@@ -2130,7 +2130,7 @@ SetDisplayAttribute (
/**
Print string for this menu option.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@param Col The column that this string will be print at.
@param Row The row that this string will be print at.
@param String The string which need to print.
@@ -2164,19 +2164,20 @@ DisplayMenuString (
// First print the highlight string.
//
SetDisplayAttribute (MenuOption, TRUE);
- Length = PrintStringAt (Col, Row, String);
+ PrintStringAt (Col, Row, String);
//
// Second, clean the empty after the string.
//
SetDisplayAttribute (MenuOption, FALSE);
+ Length = GetStringWidth (String) / 2 - 1;
PrintStringAtWithWidth (Col + Length, Row, L"", Width - Length);
}
/**
Check whether this menu can has option string.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@retval TRUE This menu option can have option string.
@retval FALSE This menu option can't have option string.
@@ -2371,7 +2372,7 @@ FxConfirmPopup (
/**
Print string for this menu option.
- @param MenuOption The menu opton which this attribut used to.
+ @param MenuOption The menu option which this attribute used to.
@param SkipWidth The skip width between the left to the start of the prompt.
@param BeginCol The begin column for one menu.
@param SkipLine The skip line for this menu.
@@ -2379,7 +2380,7 @@ FxConfirmPopup (
@param Highlight Whether this menu will be highlight.
@param UpdateCol Whether need to update the column info for Date/Time.
- @retval EFI_SUCESSS Process the user selection success.
+ @retval EFI_SUCCESS Process the user selection success.
**/
EFI_STATUS
@@ -2626,7 +2627,7 @@ DisplayOneMenu (
@param FormData The current form data info.
- @retval EFI_SUCESSS Process the user selection success.
+ @retval EFI_SUCCESS Process the user selection success.
@retval EFI_NOT_FOUND Process option string for orderedlist/Oneof fail.
**/
@@ -2904,9 +2905,9 @@ UiDisplayMenu (
case CfRefreshHighLight:
//
- // MenuOption: Last menu option that need to remove hilight
+ // MenuOption: Last menu option that need to remove highlight
// MenuOption is set to NULL in Repaint
- // NewPos: Current menu option that need to hilight
+ // NewPos: Current menu option that need to highlight
//
ControlFlag = CfUpdateHelpString;
@@ -2986,13 +2987,13 @@ UiDisplayMenu (
}
//
- // NewLine means only update highlight menu (remove old highlight and highlith
- // the new one), not need to full repain the form.
+ // NewLine means only update highlight menu (remove old highlight and highlight
+ // the new one), not need to full repaint the form.
//
if (Repaint || NewLine) {
if (IsListEmpty (&gMenuOption)) {
//
- // Don't print anything if no mwnu option.
+ // Don't print anything if no menu option.
//
StringPtr = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle);
} else {
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h
index 6e26704..a7b15a8 100644
--- a/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.h
@@ -696,8 +696,8 @@ RefreshTimeOutProcess (
/**
Record the highlight menu and top of screen menu info.
- @param Highlight The menu opton which is highlight.
- @param TopOfScreen The menu opton which is at the top of the form.
+ @param Highlight The menu option which is highlight.
+ @param TopOfScreen The menu option which is at the top of the form.
@param SkipValue The skip line info for the top of screen menu.
**/
diff --git a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
index b6dc234..b2a3ef6 100644
--- a/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
+++ b/MdeModulePkg/Universal/DisplayEngineDxe/InputHandler.c
@@ -229,8 +229,8 @@ ReadString (
case CHAR_BACKSPACE:
if ((StringPtr[0] != CHAR_NULL) && (CurrentCursor != 0)) {
- for (Index = 0; Index < CurrentCursor - 1; Index++) {
- TempString[Index] = StringPtr[Index];
+ if (CurrentCursor > 1) {
+ CopyMem (TempString, StringPtr, (CurrentCursor - 1) * sizeof (CHAR16));
}
Count = GetStringWidth (StringPtr) / 2 - 1;
@@ -261,9 +261,7 @@ ReadString (
KeyPad[1] = CHAR_NULL;
Count = GetStringWidth (StringPtr) / 2 - 1;
if (CurrentCursor < Count) {
- for (Index = 0; Index < CurrentCursor; Index++) {
- TempString[Index] = StringPtr[Index];
- }
+ CopyMem (TempString, StringPtr, CurrentCursor * sizeof (CHAR16));
TempString[Index] = CHAR_NULL;
StrCatS (TempString, MaxLen, KeyPad);
diff --git a/MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.c b/MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.c
index 4794365..d629684 100644
--- a/MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.c
+++ b/MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.c
@@ -694,6 +694,7 @@ DriverHealthManagerUpdateForm (
UINTN Index;
EFI_STRING_ID Prompt;
EFI_STRING_ID Help;
+ EFI_STRING_ID TextTwo;
CHAR16 String[512];
UINTN StringCount;
EFI_STRING TmpString;
@@ -848,11 +849,12 @@ DriverHealthManagerUpdateForm (
mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusHealthy ||
mDriverHealthManagerHealthInfo[Index].HealthStatus == EfiDriverHealthStatusFailed
);
+ TextTwo = Help;
HiiCreateTextOpCode (
StartOpCodeHandle,
Prompt,
- Help,
- 0
+ 0,
+ TextTwo
);
break;
}
@@ -872,7 +874,7 @@ DriverHealthManagerUpdateForm (
}
/**
- Called when the form is closing to remove the dynamicly added string from the HII package list.
+ Called when the form is closing to remove the dynamically added string from the HII package list.
**/
VOID
DriverHealthManagerCleanDynamicString (
diff --git a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
index 003cb49..b8c903b 100644
--- a/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
+++ b/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.c
@@ -1746,7 +1746,7 @@ DriverCallback (
@param ImageHandle Image handle this driver.
@param SystemTable Pointer to SystemTable.
- @retval EFI_SUCESS This function always complete successfully.
+ @retval EFI_SUCCESS This function always complete successfully.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
index 834c90e..cc3b3e3 100644
--- a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
@@ -1773,7 +1773,7 @@ FindSymbolStr (
Get line number and offset from this line in code file.
@param Line - Line buffer in code file
- @param Offset - Offset to functin entry
+ @param Offset - Offset to function entry
@return Line number
@@ -1867,7 +1867,7 @@ typedef enum {
Get line number from this code file.
@param Entry - Symbol entry
- @param FuncOffset - Offset to functin entry
+ @param FuncOffset - Offset to function entry
@param SearchType - Search type for the code
@return Line number
@@ -2045,7 +2045,7 @@ EdbGetSourceStrFromCodeByLine (
Get source string from this code file.
@param Entry - Symbol entry
- @param FuncOffset - Offset to functin entry
+ @param FuncOffset - Offset to function entry
@param FuncEnd - Function end
@retval Funtion start
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
index 508184f..5c168c8 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/FtwMisc.c
@@ -810,12 +810,18 @@ FtwGetLastWriteHeader (
FtwHeader = (EFI_FAULT_TOLERANT_WRITE_HEADER *)(FtwWorkSpaceHeader + 1);
Offset = sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER);
+ if (!CompareGuid (&FtwWorkSpaceHeader->Signature, &gEdkiiWorkingBlockSignatureGuid)) {
+ *FtwWriteHeader = FtwHeader;
+ return EFI_ABORTED;
+ }
+
while (FtwHeader->Complete == FTW_VALID_STATE) {
Offset += FTW_WRITE_TOTAL_SIZE (FtwHeader->NumberOfWrites, FtwHeader->PrivateDataSize);
//
// If Offset exceed the FTW work space boudary, return error.
//
- if (Offset >= FtwWorkSpaceSize) {
+
+ if ((Offset + sizeof (EFI_FAULT_TOLERANT_WRITE_HEADER)) >= FtwWorkSpaceSize) {
*FtwWriteHeader = FtwHeader;
return EFI_ABORTED;
}
@@ -1294,7 +1300,10 @@ InitFtwProtocol (
// Refresh the working space data from working block
//
Status = WorkSpaceRefresh (FtwDevice);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Ftw: Init.. WorkSpaceRefresh failed: Status = %r\n", Status));
+ }
+
//
// If the working block workspace is not valid, try the spare block
//
diff --git a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
index fd56364..caa87e9 100644
--- a/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
+++ b/MdeModulePkg/Universal/FaultTolerantWriteDxe/UpdateWorkingBlock.c
@@ -286,6 +286,10 @@ WorkSpaceRefresh (
return EFI_ABORTED;
}
+ if (!IsValidWorkSpace (FtwDevice->FtwWorkSpaceHeader)) {
+ return EFI_ABORTED;
+ }
+
//
// Refresh the FtwLastWriteHeader
//
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
index 5ae6189..c9aabaa 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
@@ -1372,6 +1372,149 @@ GetSupportedLanguages (
}
/**
+ This function create a new string in String Package or updates an existing
+ string in a String Package. If StringId is 0, then a new string is added to
+ a String Package. If StringId is not zero, then a string in String Package is
+ updated. If SupportedLanguages is NULL, then the string is added or updated
+ for all the languages that the String Package supports. If SupportedLanguages
+ is not NULL, then the string is added or updated for the set of languages
+ specified by SupportedLanguages.
+
+ If HiiHandle is NULL, then ASSERT().
+ If String is NULL, then ASSERT().
+
+ @param[in] HiiHandle A handle that was previously registered in the
+ HII Database.
+ @param[in] StringId If zero, then a new string is created in the
+ String Package associated with HiiHandle. If
+ non-zero, then the string specified by StringId
+ is updated in the String Package associated
+ with HiiHandle.
+ @param[in] String A pointer to the Null-terminated Unicode string
+ to add or update in the String Package associated
+ with HiiHandle.
+ @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string of
+ language codes. If this parameter is NULL, then
+ String is added or updated in the String Package
+ associated with HiiHandle for all the languages
+ that the String Package supports. If this
+ parameter is not NULL, then then String is added
+ or updated in the String Package associated with
+ HiiHandle for the set oflanguages specified by
+ SupportedLanguages. The format of
+ SupportedLanguages must follow the language
+ format assumed the HII Database.
+
+ @retval 0 The string could not be added or updated in the String Package.
+ @retval Other The EFI_STRING_ID of the newly added or updated string.
+
+**/
+EFI_STRING_ID
+InternalHiiSetString (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId OPTIONAL,
+ IN CONST EFI_STRING String,
+ IN CONST CHAR8 *SupportedLanguages OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *AllocatedLanguages;
+ CHAR8 *Supported;
+ CHAR8 *Language;
+
+ ASSERT (HiiHandle != NULL);
+
+ if (SupportedLanguages == NULL) {
+ //
+ // Retrieve the languages that the package specified by HiiHandle supports
+ //
+ AllocatedLanguages = GetSupportedLanguages (HiiHandle);
+ } else {
+ //
+ // Allocate a copy of the SupportLanguages string that passed in
+ //
+ AllocatedLanguages = AllocateCopyPool (AsciiStrSize (SupportedLanguages), SupportedLanguages);
+ }
+
+ //
+ // If there are not enough resources for the supported languages string, then return a StringId of 0
+ //
+ if (AllocatedLanguages == NULL) {
+ return (EFI_STRING_ID)(0);
+ }
+
+ Status = EFI_INVALID_PARAMETER;
+ //
+ // Loop through each language that the string supports
+ //
+ for (Supported = AllocatedLanguages; *Supported != '\0'; ) {
+ //
+ // Cache a pointer to the beginning of the current language in the list of languages
+ //
+ Language = Supported;
+
+ //
+ // Search for the next language separator and replace it with a Null-terminator
+ //
+ for ( ; *Supported != 0 && *Supported != ';'; Supported++) {
+ }
+
+ if (*Supported != 0) {
+ *(Supported++) = '\0';
+ }
+
+ if ((SupportedLanguages == NULL) && (AsciiStrnCmp (Language, UEFI_CONFIG_LANG, AsciiStrLen (UEFI_CONFIG_LANG)) == 0)) {
+ //
+ // Skip string package used for keyword protocol.
+ //
+ continue;
+ }
+
+ //
+ // If StringId is 0, then call NewString(). Otherwise, call SetString()
+ //
+ if (StringId == (EFI_STRING_ID)(0)) {
+ Status = mPrivate.HiiString.NewString (
+ &mPrivate.HiiString,
+ HiiHandle,
+ &StringId,
+ Language,
+ NULL,
+ String,
+ NULL
+ );
+ } else {
+ Status = mPrivate.HiiString.SetString (
+ &mPrivate.HiiString,
+ HiiHandle,
+ StringId,
+ Language,
+ String,
+ NULL
+ );
+ }
+
+ //
+ // If there was an error, then break out of the loop and return a StringId of 0
+ //
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ //
+ // Free the buffer of supported languages
+ //
+ FreePool (AllocatedLanguages);
+
+ if (EFI_ERROR (Status)) {
+ return (EFI_STRING_ID)(0);
+ } else {
+ return StringId;
+ }
+}
+
+/**
Retrieves a string from a string package.
If HiiHandle is NULL, then ASSERT().
@@ -2202,6 +2345,7 @@ ParseIfrData (
BOOLEAN SmallestIdFromFlag;
BOOLEAN FromOtherDefaultOpcode;
BOOLEAN QuestionReferBitField;
+ UINT16 *StringData;
Status = EFI_SUCCESS;
BlockData = NULL;
@@ -2215,6 +2359,7 @@ ParseIfrData (
FromOtherDefaultOpcode = FALSE;
QuestionReferBitField = FALSE;
IfrEfiVarStoreTmp = NULL;
+ StringData = NULL;
//
// Go through the form package to parse OpCode one by one.
@@ -2871,6 +3016,33 @@ ParseIfrData (
goto Done;
}
+ if (IfrEfiVarStoreTmp == NULL) {
+ break;
+ }
+
+ //
+ // Set default value base on the DefaultId list get from IFR data.
+ //
+ NvDefaultStoreSize = PcdGetSize (PcdNvStoreDefaultValueBuffer);
+ for (LinkData = DefaultIdArray->Entry.ForwardLink; LinkData != &DefaultIdArray->Entry; LinkData = LinkData->ForwardLink) {
+ DefaultDataPtr = BASE_CR (LinkData, IFR_DEFAULT_DATA, Entry);
+ DefaultData.DefaultId = DefaultDataPtr->DefaultId;
+ if (NvDefaultStoreSize > sizeof (PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) {
+ StringData = AllocateZeroPool (VarWidth*2);
+ if (StringData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ FindQuestionDefaultSetting (DefaultData.DefaultId, IfrEfiVarStoreTmp, &(IfrString->Question), (VOID *)StringData, VarWidth, QuestionReferBitField);
+ if ((DefaultData.Value.string != 0) && (StringData != NULL)) {
+ DefaultData.Value.string = InternalHiiSetString (HiiHandle, 0, StringData, NULL);
+ InsertDefaultValue (BlockData, &DefaultData);
+ FreePool (StringData);
+ }
+ }
+ }
+
break;
case EFI_IFR_PASSWORD_OP:
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
index 0b09c24..314e408 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Database.c
@@ -574,6 +574,45 @@ IsEfiVarStoreQuestion (
@return Pointer to the matched variable header or NULL if not found.
**/
+AUTHENTICATED_VARIABLE_HEADER *
+AuthFindVariableData (
+ IN VARIABLE_STORE_HEADER *VariableStorage,
+ IN EFI_GUID *VarGuid,
+ IN UINT32 VarAttribute,
+ IN CHAR16 *VarName
+ )
+{
+ AUTHENTICATED_VARIABLE_HEADER *VariableHeader;
+ AUTHENTICATED_VARIABLE_HEADER *VariableEnd;
+
+ VariableEnd = (AUTHENTICATED_VARIABLE_HEADER *)((UINT8 *)VariableStorage + VariableStorage->Size);
+ VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)(VariableStorage + 1);
+ VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
+ while (VariableHeader < VariableEnd) {
+ if (CompareGuid (&VariableHeader->VendorGuid, VarGuid) &&
+ (VariableHeader->Attributes == VarAttribute) &&
+ (StrCmp (VarName, (CHAR16 *)(VariableHeader + 1)) == 0))
+ {
+ return VariableHeader;
+ }
+
+ VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)((UINT8 *)VariableHeader + sizeof (AUTHENTICATED_VARIABLE_HEADER) + VariableHeader->NameSize + VariableHeader->DataSize);
+ VariableHeader = (AUTHENTICATED_VARIABLE_HEADER *)HEADER_ALIGN (VariableHeader);
+ }
+
+ return NULL;
+}
+
+/**
+ Find the matched variable from the input variable storage.
+
+ @param[in] VariableStorage Point to the variable storage header.
+ @param[in] VarGuid A unique identifier for the variable.
+ @param[in] VarAttribute The attributes bitmask for the variable.
+ @param[in] VarName A Null-terminated ascii string that is the name of the variable.
+
+ @return Pointer to the matched variable header or NULL if not found.
+**/
VARIABLE_HEADER *
FindVariableData (
IN VARIABLE_STORE_HEADER *VariableStorage,
@@ -626,25 +665,32 @@ FindQuestionDefaultSetting (
IN BOOLEAN BitFieldQuestion
)
{
- VARIABLE_HEADER *VariableHeader;
- VARIABLE_STORE_HEADER *VariableStorage;
- LIST_ENTRY *Link;
- VARSTORAGE_DEFAULT_DATA *Entry;
- VARIABLE_STORE_HEADER *NvStoreBuffer;
- UINT8 *DataBuffer;
- UINT8 *BufferEnd;
- BOOLEAN IsFound;
- UINTN Index;
- UINT32 BufferValue;
- UINT32 BitFieldVal;
- UINTN BitOffset;
- UINTN ByteOffset;
- UINTN BitWidth;
- UINTN StartBit;
- UINTN EndBit;
- PCD_DEFAULT_DATA *DataHeader;
- PCD_DEFAULT_INFO *DefaultInfo;
- PCD_DATA_DELTA *DeltaData;
+ AUTHENTICATED_VARIABLE_HEADER *AuthVariableHeader;
+ VARIABLE_HEADER *VariableHeader;
+ VARIABLE_STORE_HEADER *VariableStorage;
+ LIST_ENTRY *Link;
+ VARSTORAGE_DEFAULT_DATA *Entry;
+ VARIABLE_STORE_HEADER *NvStoreBuffer;
+ UINT8 *DataBuffer;
+ UINT8 *BufferEnd;
+ BOOLEAN IsFound;
+ UINTN Index;
+ UINT32 BufferValue;
+ UINT32 BitFieldVal;
+ UINTN BitOffset;
+ UINTN ByteOffset;
+ UINTN BitWidth;
+ UINTN StartBit;
+ UINTN EndBit;
+ PCD_DEFAULT_DATA *DataHeader;
+ PCD_DEFAULT_INFO *DefaultInfo;
+ PCD_DATA_DELTA *DeltaData;
+ BOOLEAN VarCheck;
+
+ if (EfiVarStore == NULL) {
+ DEBUG ((DEBUG_ERROR, "EfiVarStore is null\n"));
+ return EFI_NOT_FOUND;
+ }
if (gSkuId == 0xFFFFFFFFFFFFFFFF) {
gSkuId = LibPcdGetSku ();
@@ -750,40 +796,81 @@ FindQuestionDefaultSetting (
return EFI_NOT_FOUND;
}
- //
- // Find the question default value from the variable storage
- //
- VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *)EfiVarStore->Name);
- if (VariableHeader == NULL) {
- return EFI_NOT_FOUND;
- }
+ VarCheck = (BOOLEAN)(CompareGuid (&VariableStorage->Signature, &gEfiAuthenticatedVariableGuid));
- StartBit = 0;
- EndBit = 0;
- ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
- if (BitFieldQuestion) {
- BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
- ByteOffset = BitOffset / 8;
- BitWidth = Width;
- StartBit = BitOffset % 8;
- EndBit = StartBit + BitWidth - 1;
- Width = EndBit / 8 + 1;
- }
+ if (VarCheck) {
+ //
+ // Find the question default value from the variable storage
+ //
+ AuthVariableHeader = AuthFindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *)EfiVarStore->Name);
+ if (AuthVariableHeader == NULL) {
+ return EFI_NOT_FOUND;
+ }
- if (VariableHeader->DataSize < ByteOffset + Width) {
- return EFI_INVALID_PARAMETER;
- }
+ StartBit = 0;
+ EndBit = 0;
+ ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+ if (BitFieldQuestion) {
+ BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+ ByteOffset = BitOffset / 8;
+ BitWidth = Width;
+ StartBit = BitOffset % 8;
+ EndBit = StartBit + BitWidth - 1;
+ Width = EndBit / 8 + 1;
+ }
- //
- // Copy the question value
- //
- if (ValueBuffer != NULL) {
+ if (AuthVariableHeader->DataSize < ByteOffset + Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Copy the question value
+ //
+ if (ValueBuffer != NULL) {
+ if (BitFieldQuestion) {
+ CopyMem (&BufferValue, (UINT8 *)AuthVariableHeader + sizeof (AUTHENTICATED_VARIABLE_HEADER) + AuthVariableHeader->NameSize + ByteOffset, Width);
+ BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
+ CopyMem (ValueBuffer, &BitFieldVal, sizeof (UINT32));
+ } else {
+ CopyMem (ValueBuffer, (UINT8 *)AuthVariableHeader + sizeof (AUTHENTICATED_VARIABLE_HEADER) + AuthVariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
+ }
+ }
+ } else {
+ //
+ // Find the question default value from the variable storage
+ //
+ VariableHeader = FindVariableData (VariableStorage, &EfiVarStore->Guid, EfiVarStore->Attributes, (CHAR16 *)EfiVarStore->Name);
+ if (VariableHeader == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ StartBit = 0;
+ EndBit = 0;
+ ByteOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
if (BitFieldQuestion) {
- CopyMem (&BufferValue, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);
- BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
- CopyMem (ValueBuffer, &BitFieldVal, Width);
- } else {
- CopyMem (ValueBuffer, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
+ BitOffset = IfrQuestionHdr->VarStoreInfo.VarOffset;
+ ByteOffset = BitOffset / 8;
+ BitWidth = Width;
+ StartBit = BitOffset % 8;
+ EndBit = StartBit + BitWidth - 1;
+ Width = EndBit / 8 + 1;
+ }
+
+ if (VariableHeader->DataSize < ByteOffset + Width) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Copy the question value
+ //
+ if (ValueBuffer != NULL) {
+ if (BitFieldQuestion) {
+ CopyMem (&BufferValue, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + ByteOffset, Width);
+ BitFieldVal = BitFieldRead32 (BufferValue, StartBit, EndBit);
+ CopyMem (ValueBuffer, &BitFieldVal, sizeof (UINT32));
+ } else {
+ CopyMem (ValueBuffer, (UINT8 *)VariableHeader + sizeof (VARIABLE_HEADER) + VariableHeader->NameSize + IfrQuestionHdr->VarStoreInfo.VarOffset, Width);
+ }
}
}
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
index 0116fb6..5123332 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
@@ -86,6 +86,7 @@
gEfiHiiImageDecoderNameJpegGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES ## GUID
gEfiHiiImageDecoderNamePngGuid |gEfiMdeModulePkgTokenSpaceGuid.PcdSupportHiiImageProtocol ## SOMETIMES_CONSUMES ## GUID
gEdkiiIfrBitVarstoreGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiAuthenticatedVariableGuid ## CONSUMES ## GUID
[Depex]
TRUE
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
index ab8f056..ae5eff7 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
@@ -242,19 +242,19 @@ Output1bitPixel (
IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
)
{
- UINT16 Xpos;
- UINT16 Ypos;
- UINTN OffsetY;
- UINT8 Index;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[2];
- EFI_HII_IMAGE_PALETTE_INFO *Palette;
- UINTN PaletteSize;
- UINT8 Byte;
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ UINT8 Index;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION PaletteValue[2];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT8 Byte;
ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
- BitMapPtr = Image->Bitmap;
+ BitMapPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)Image->Bitmap;
//
// First entry corresponds to color 0 and second entry corresponds to color 1.
@@ -271,8 +271,8 @@ Output1bitPixel (
CopyMem (Palette, PaletteInfo, PaletteSize);
ZeroMem (PaletteValue, sizeof (PaletteValue));
- CopyRgbToGopPixel (&PaletteValue[0], &Palette->PaletteValue[0], 1);
- CopyRgbToGopPixel (&PaletteValue[1], &Palette->PaletteValue[1], 1);
+ CopyRgbToGopPixel (&PaletteValue[0].Pixel, &Palette->PaletteValue[0], 1);
+ CopyRgbToGopPixel (&PaletteValue[1].Pixel, &Palette->PaletteValue[1], 1);
FreePool (Palette);
//
@@ -287,9 +287,9 @@ Output1bitPixel (
Byte = *(Data + OffsetY + Xpos);
for (Index = 0; Index < 8; Index++) {
if ((Byte & (1 << Index)) != 0) {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[1];
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)].Raw = PaletteValue[1].Raw;
} else {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)] = PaletteValue[0];
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + (8 - Index - 1)].Raw = PaletteValue[0].Raw;
}
}
}
@@ -301,9 +301,9 @@ Output1bitPixel (
Byte = *(Data + OffsetY + Xpos);
for (Index = 0; Index < Image->Width % 8; Index++) {
if ((Byte & (1 << (8 - Index - 1))) != 0) {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[1];
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index].Raw = PaletteValue[1].Raw;
} else {
- BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index] = PaletteValue[0];
+ BitMapPtr[Ypos * Image->Width + Xpos * 8 + Index].Raw = PaletteValue[0].Raw;
}
}
}
@@ -331,19 +331,19 @@ Output4bitPixel (
IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
)
{
- UINT16 Xpos;
- UINT16 Ypos;
- UINTN OffsetY;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[16];
- EFI_HII_IMAGE_PALETTE_INFO *Palette;
- UINTN PaletteSize;
- UINT16 PaletteNum;
- UINT8 Byte;
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION PaletteValue[16];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
- BitMapPtr = Image->Bitmap;
+ BitMapPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)Image->Bitmap;
//
// The bitmap should allocate each color index starting from 0.
@@ -361,7 +361,7 @@ Output4bitPixel (
PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
ZeroMem (PaletteValue, sizeof (PaletteValue));
- CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
+ CopyRgbToGopPixel (&PaletteValue->Pixel, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
FreePool (Palette);
//
@@ -373,17 +373,17 @@ Output4bitPixel (
// All bits in these bytes are meaningful
//
for (Xpos = 0; Xpos < Image->Width / 2; Xpos++) {
- Byte = *(Data + OffsetY + Xpos);
- BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
- BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1] = PaletteValue[Byte & 0x0F];
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[Ypos * Image->Width + Xpos * 2].Raw = PaletteValue[Byte >> 4].Raw;
+ BitMapPtr[Ypos * Image->Width + Xpos * 2 + 1].Raw = PaletteValue[Byte & 0x0F].Raw;
}
if (Image->Width % 2 != 0) {
//
// Padding bits in this byte should be ignored.
//
- Byte = *(Data + OffsetY + Xpos);
- BitMapPtr[Ypos * Image->Width + Xpos * 2] = PaletteValue[Byte >> 4];
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[Ypos * Image->Width + Xpos * 2].Raw = PaletteValue[Byte >> 4].Raw;
}
}
}
@@ -409,19 +409,19 @@ Output8bitPixel (
IN EFI_HII_IMAGE_PALETTE_INFO *PaletteInfo
)
{
- UINT16 Xpos;
- UINT16 Ypos;
- UINTN OffsetY;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BitMapPtr;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL PaletteValue[256];
- EFI_HII_IMAGE_PALETTE_INFO *Palette;
- UINTN PaletteSize;
- UINT16 PaletteNum;
- UINT8 Byte;
+ UINT16 Xpos;
+ UINT16 Ypos;
+ UINTN OffsetY;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *BitMapPtr;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION PaletteValue[256];
+ EFI_HII_IMAGE_PALETTE_INFO *Palette;
+ UINTN PaletteSize;
+ UINT16 PaletteNum;
+ UINT8 Byte;
ASSERT (Image != NULL && Data != NULL && PaletteInfo != NULL);
- BitMapPtr = Image->Bitmap;
+ BitMapPtr = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)Image->Bitmap;
//
// The bitmap should allocate each color index starting from 0.
@@ -438,7 +438,7 @@ Output8bitPixel (
CopyMem (Palette, PaletteInfo, PaletteSize);
PaletteNum = (UINT16)(Palette->PaletteSize / sizeof (EFI_HII_RGB_PIXEL));
ZeroMem (PaletteValue, sizeof (PaletteValue));
- CopyRgbToGopPixel (PaletteValue, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
+ CopyRgbToGopPixel (&PaletteValue->Pixel, Palette->PaletteValue, MIN (PaletteNum, ARRAY_SIZE (PaletteValue)));
FreePool (Palette);
//
@@ -450,8 +450,8 @@ Output8bitPixel (
// All bits are meaningful since the bitmap is 8 bits per pixel.
//
for (Xpos = 0; Xpos < Image->Width; Xpos++) {
- Byte = *(Data + OffsetY + Xpos);
- BitMapPtr[OffsetY + Xpos] = PaletteValue[Byte];
+ Byte = *(Data + OffsetY + Xpos);
+ BitMapPtr[OffsetY + Xpos].Raw = PaletteValue[Byte].Raw;
}
}
}
@@ -521,13 +521,15 @@ ImageToBlt (
IN OUT EFI_IMAGE_OUTPUT **Blt
)
{
- EFI_IMAGE_OUTPUT *ImageOut;
- UINTN Xpos;
- UINTN Ypos;
- UINTN OffsetY1; // src buffer
- UINTN OffsetY2; // dest buffer
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL SrcPixel;
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL ZeroPixel;
+ EFI_IMAGE_OUTPUT *ImageOut;
+ UINTN Xpos;
+ UINTN Ypos;
+ UINTN OffsetY1; // src buffer
+ UINTN OffsetY2; // dest buffer
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION SrcPixel;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION ZeroPixel;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *BltBufferPixel;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *ImageBitmap;
if ((BltBuffer == NULL) || (Blt == NULL) || (*Blt == NULL)) {
return EFI_INVALID_PARAMETER;
@@ -545,17 +547,20 @@ ImageToBlt (
ZeroMem (&ZeroPixel, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));
+ BltBufferPixel = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)BltBuffer;
+ ImageBitmap = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION *)ImageOut->Image.Bitmap;
+
for (Ypos = 0; Ypos < Height; Ypos++) {
OffsetY1 = Width * Ypos;
OffsetY2 = ImageOut->Width * (BltY + Ypos);
for (Xpos = 0; Xpos < Width; Xpos++) {
- SrcPixel = BltBuffer[OffsetY1 + Xpos];
+ SrcPixel.Raw = BltBufferPixel[OffsetY1 + Xpos].Raw;
if (Transparent) {
if (CompareMem (&SrcPixel, &ZeroPixel, 3) != 0) {
- ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
+ ImageBitmap[OffsetY2 + BltX + Xpos].Raw = SrcPixel.Raw;
}
} else {
- ImageOut->Image.Bitmap[OffsetY2 + BltX + Xpos] = SrcPixel;
+ ImageBitmap[OffsetY2 + BltX + Xpos].Raw = SrcPixel.Raw;
}
}
}
@@ -1402,7 +1407,7 @@ HiiDrawImage (
//
if ((Flags & EFI_HII_DIRECT_TO_SCREEN) == EFI_HII_DIRECT_TO_SCREEN) {
//
- // Caller should make sure the current UGA console is grarphic mode.
+ // Caller should make sure the current console is grarphic mode.
//
//
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
index e3fceed..c70f308 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/String.c
@@ -1000,7 +1000,7 @@ SetStringWorker (
case EFI_HII_SIBT_STRING_SCSU_FONT:
case EFI_HII_SIBT_STRINGS_SCSU:
case EFI_HII_SIBT_STRINGS_SCSU_FONT:
- BlockSize = OldBlockSize + StrLen (String);
+ BlockSize = OldBlockSize + StrSize (String);
BlockSize -= AsciiStrSize ((CHAR8 *)StringTextPtr);
Block = AllocateZeroPool (BlockSize);
if (Block == NULL) {
diff --git a/MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSample.c b/MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSample.c
index dd0ae50..cbcb7b2 100644
--- a/MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSample.c
+++ b/MdeModulePkg/Universal/HiiResourcesSampleDxe/HiiResourcesSample.c
@@ -57,7 +57,7 @@ HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
@param[in] ImageHandle Image handle this driver.
@param[in] SystemTable Pointer to SystemTable.
- @retval EFI_SUCESS This function always complete successfully.
+ @retval EFI_SUCCESS This function always complete successfully.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
index 3aa7660..e30a55f 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c
@@ -6,9 +6,9 @@
drivers to controllers.
The main flow:
- 1. It dynamicly locate all controller device path.
- 2. It dynamicly locate all drivers which support binding protocol.
- 3. It export and dynamicly update two menu to let user select the
+ 1. It dynamically locate all controller device path.
+ 2. It dynamically locate all drivers which support binding protocol.
+ 3. It export and dynamically update two menu to let user select the
mapping between drivers to controllers.
4. It save all the mapping info in NV variables which will be consumed
by platform override protocol driver to publish the platform override protocol.
@@ -421,6 +421,8 @@ UpdateDeviceSelectPage (
&mDevicePathHandleBuffer
);
if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) {
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
return EFI_SUCCESS;
}
@@ -708,6 +710,8 @@ UpdateBindingDriverSelectPage (
&mDriverImageHandleBuffer
);
if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) {
+ HiiFreeOpCodeHandle (StartOpCodeHandle);
+ HiiFreeOpCodeHandle (EndOpCodeHandle);
return EFI_NOT_FOUND;
}
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.uni b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.uni
index 9905a28..8f81593 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.uni
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.uni
@@ -10,9 +10,9 @@
// drivers to controllers.
//
// The main flow:
-// 1. It dynamicly locate all controller device path.
-// 2. It dynamicly locate all drivers which support binding protocol.
-// 3. It export and dynamicly update two menu to let user select the
+// 1. It dynamically locate all controller device path.
+// 2. It dynamically locate all drivers which support binding protocol.
+// 3. It export and dynamically update two menu to let user select the
// mapping between drivers to controllers.
// 4. It save all the mapping info in NV variables for the following boot,
// which will be consumed by GetDriver API of the produced the platform override protocol.
@@ -32,6 +32,6 @@
"The main flow:<BR>\n"
"1. It dynamically locates all controller device path.<BR>\n"
"2. It dynamically locates all drivers which support binding protocol.<BR>\n"
- "3. It exports and dynamicly updates two menu to let user select the mapping between drivers to controllers.<BR>\n"
+ "3. It exports and dynamically updates two menu to let user select the mapping between drivers to controllers.<BR>\n"
"4. It saves all the mapping info in NV variables for the following boot, which will be consumed by GetDriver API of the produced the platform override protocol.<BR>"
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h
index 0e200c0..fbc9c8f 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h
@@ -1,6 +1,6 @@
/** @file
- The defintions are required both by Source code and Vfr file.
+ The definitions are required both by Source code and Vfr file.
The PLAT_OVER_MNGR_DATA structure, form guid and Ifr question ID are defined.
Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
index 97c8e3c..e12d784 100644
--- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
+++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf
@@ -9,9 +9,9 @@
# drivers to controllers.
#
# The main flow:
-# 1. It dynamicly locate all controller device path.
-# 2. It dynamicly locate all drivers which support binding protocol.
-# 3. It export and dynamicly update two menu to let user select the
+# 1. It dynamically locate all controller device path.
+# 2. It dynamically locate all drivers which support binding protocol.
+# 3. It export and dynamically update two menu to let user select the
# mapping between drivers to controllers.
# 4. It save all the mapping info in NV variables for the following boot,
# which will be consumed by GetDriver API of the produced the platform override protocol.
diff --git a/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.h b/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.h
index 8931f8e..ee173d5 100644
--- a/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.h
+++ b/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.h
@@ -32,6 +32,7 @@
typedef UINTN size_t;
typedef UINT32 uint32_t;
typedef INTN intptr_t;
+typedef INT64 ptrdiff_t;
#ifndef offsetof
#define offsetof OFFSET_OF
diff --git a/MdeModulePkg/Universal/RegularExpressionDxe/oniguruma b/MdeModulePkg/Universal/RegularExpressionDxe/oniguruma
-Subproject abfc8ff81df4067f309032467785e06975678f0
+Subproject 4ef89209a239c1aea328cf13c05a2807e5c146d
diff --git a/MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.c b/MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.c
index b123983..e1b1021 100644
--- a/MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.c
+++ b/MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.c
@@ -275,7 +275,7 @@ ReportDispatcher (
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
- @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
+ @retval EFI_SUCCESS The entry point of DXE IPL PEIM executes successfully.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.c b/MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.c
index 8a11643..5229fd8 100644
--- a/MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.c
+++ b/MdeModulePkg/Universal/SectionExtractionPei/SectionExtractionPei.c
@@ -251,12 +251,15 @@ SectionExtractionPeiEntry (
if (ExtractHandlerNumber > 0) {
GuidPpi = (EFI_PEI_PPI_DESCRIPTOR *)AllocatePool (ExtractHandlerNumber * sizeof (EFI_PEI_PPI_DESCRIPTOR));
ASSERT (GuidPpi != NULL);
- while (ExtractHandlerNumber-- > 0) {
- GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
- GuidPpi->Ppi = (VOID *)&mCustomGuidedSectionExtractionPpi;
- GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];
- Status = PeiServicesInstallPpi (GuidPpi++);
- ASSERT_EFI_ERROR (Status);
+
+ if (GuidPpi != NULL) {
+ while (ExtractHandlerNumber-- > 0) {
+ GuidPpi->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ GuidPpi->Ppi = (VOID *)&mCustomGuidedSectionExtractionPpi;
+ GuidPpi->Guid = &ExtractHandlerGuidTable[ExtractHandlerNumber];
+ Status = PeiServicesInstallPpi (GuidPpi++);
+ ASSERT_EFI_ERROR (Status);
+ }
}
}
diff --git a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
index de7e79e..e44a70c 100644
--- a/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
+++ b/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -1004,7 +1004,7 @@ UpdateStatementStatus (
@param Action The user input action request info.
@param DefaultId The user input default Id info.
- @retval EFI_SUCESSS This function always return successfully for now.
+ @retval EFI_SUCCESS This function always return successfully for now.
**/
EFI_STATUS
@@ -1557,7 +1557,7 @@ ProcessQuestionConfig (
@param UserInput The user input data.
- @retval EFI_SUCESSS This function always return successfully for now.
+ @retval EFI_SUCCESS This function always return successfully for now.
**/
EFI_STATUS
@@ -1687,7 +1687,7 @@ ProcessUserInput (
Display form and wait for user to select one menu option, then return it.
- @retval EFI_SUCESSS This function always return successfully for now.
+ @retval EFI_SUCCESS This function always return successfully for now.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.c b/MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.c
index d61edc8..9c7d390 100644
--- a/MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.c
+++ b/MdeModulePkg/Universal/SmbiosMeasurementDxe/SmbiosMeasurementDxe.c
@@ -637,6 +637,10 @@ MeasureSmbiosTable (
if (!EFI_ERROR (Status)) {
gBS->CloseEvent (Event);
}
+
+ if (TableAddress != NULL) {
+ FreePool (TableAddress);
+ }
}
return;
diff --git a/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.c b/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.c
index 663cfff..8121e0c 100644
--- a/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.c
+++ b/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.c
@@ -19,7 +19,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
#include <Library/UefiLib.h>
+#include <Guid/MmCommBuffer.h>
#include <Guid/PiSmmCommunicationRegionTable.h>
#define DEFAULT_COMMON_PI_SMM_COMMUNIATION_REGION_PAGES 4
@@ -44,8 +46,11 @@ SmmCommunicationBufferEntryPoint (
UINT32 DescriptorSize;
EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
EFI_MEMORY_DESCRIPTOR *Entry;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ MM_COMM_BUFFER *MmCommBuffer;
DescriptorSize = sizeof (EFI_MEMORY_DESCRIPTOR);
+
//
// Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will
// prevent people from having pointer math bugs in their code.
@@ -58,6 +63,10 @@ SmmCommunicationBufferEntryPoint (
//
PiSmmCommunicationRegionTable = AllocateReservedPool (sizeof (EDKII_PI_SMM_COMMUNICATION_REGION_TABLE) + DescriptorSize);
ASSERT (PiSmmCommunicationRegionTable != NULL);
+ if (PiSmmCommunicationRegionTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
ZeroMem (PiSmmCommunicationRegionTable, sizeof (EDKII_PI_SMM_COMMUNICATION_REGION_TABLE) + DescriptorSize);
PiSmmCommunicationRegionTable->Version = EDKII_PI_SMM_COMMUNICATION_REGION_TABLE_VERSION;
@@ -65,11 +74,21 @@ SmmCommunicationBufferEntryPoint (
PiSmmCommunicationRegionTable->DescriptorSize = DescriptorSize;
Entry = (EFI_MEMORY_DESCRIPTOR *)(PiSmmCommunicationRegionTable + 1);
Entry->Type = EfiConventionalMemory;
- Entry->PhysicalStart = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedPages (DEFAULT_COMMON_PI_SMM_COMMUNIATION_REGION_PAGES);
+
+ GuidHob = GetFirstGuidHob (&gMmCommBufferHobGuid);
+
+ if (GuidHob == NULL) {
+ Entry->PhysicalStart = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateReservedPages (DEFAULT_COMMON_PI_SMM_COMMUNIATION_REGION_PAGES);
+ Entry->NumberOfPages = DEFAULT_COMMON_PI_SMM_COMMUNIATION_REGION_PAGES;
+ } else {
+ MmCommBuffer = GET_GUID_HOB_DATA (GuidHob);
+ Entry->PhysicalStart = MmCommBuffer->PhysicalStart;
+ Entry->NumberOfPages = MmCommBuffer->NumberOfPages;
+ }
+
ASSERT (Entry->PhysicalStart != 0);
- Entry->VirtualStart = 0;
- Entry->NumberOfPages = DEFAULT_COMMON_PI_SMM_COMMUNIATION_REGION_PAGES;
- Entry->Attribute = 0;
+ Entry->VirtualStart = 0;
+ Entry->Attribute = 0;
DEBUG ((DEBUG_INFO, "PiSmmCommunicationRegionTable:(0x%x)\n", PiSmmCommunicationRegionTable));
DEBUG ((DEBUG_INFO, " Version - 0x%x\n", PiSmmCommunicationRegionTable->Version));
diff --git a/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf b/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf
index 5c867ba..1c9bbdc 100644
--- a/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf
+++ b/MdeModulePkg/Universal/SmmCommunicationBufferDxe/SmmCommunicationBufferDxe.inf
@@ -47,6 +47,7 @@
[Guids]
gEdkiiPiSmmCommunicationRegionTableGuid ## PRODUCES ## SystemTable
+ gMmCommBufferHobGuid ## CONSUMES
[Depex]
TRUE
diff --git a/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c b/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c
index d740a62..b29b78b 100644
--- a/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c
+++ b/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c
@@ -19,7 +19,7 @@
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
- @retval EFI_SUCESS The entry point of DXE IPL PEIM executes successfully.
+ @retval EFI_SUCCESS The entry point of DXE IPL PEIM executes successfully.
**/
EFI_STATUS
diff --git a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c
index 6286210..77f7052 100644
--- a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c
+++ b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c
@@ -27,7 +27,7 @@ InitializationDispatcherWorker (
// If enable UseSerial, then initialize serial port.
// if enable UseRuntimeMemory, then initialize runtime memory status code worker.
//
- if (PcdGetBool (PcdStatusCodeUseSerial)) {
+ if (IsStatusCodeUsingSerialPort ()) {
//
// Call Serial Port Lib API to initialize serial port.
//
@@ -68,7 +68,7 @@ StatusCodeHandlerCommonEntry (
//
InitializationDispatcherWorker ();
- if (PcdGetBool (PcdStatusCodeUseSerial)) {
+ if (IsStatusCodeUsingSerialPort ()) {
mRscHandlerProtocol->Register (SerialStatusCodeReportWorker);
}
diff --git a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h
index e416220..79ff005 100644
--- a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h
+++ b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h
@@ -126,4 +126,18 @@ StatusCodeHandlerCommonEntry (
VOID
);
+/**
+ Check if the status code is using serial port.
+
+ This function determines whether the status code reporting mechanism
+ is configured to use the serial port.
+
+ @retval TRUE Status code is using the serial port.
+ @retval FALSE Status code is not using the serial port.
+**/
+BOOLEAN
+IsStatusCodeUsingSerialPort (
+ VOID
+ );
+
#endif
diff --git a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c
index 11a6170..67ff33f 100644
--- a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c
+++ b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c
@@ -8,6 +8,33 @@
**/
#include "StatusCodeHandlerMm.h"
+#include <Guid/MmStatusCodeUseSerial.h>
+#include <Library/HobLib.h>
+
+/**
+ Check if the status code is using serial port.
+
+ This function determines whether the status code reporting mechanism
+ is configured to use the serial port.
+
+ @retval TRUE Status code is using the serial port.
+ @retval FALSE Status code is not using the serial port.
+**/
+BOOLEAN
+IsStatusCodeUsingSerialPort (
+ VOID
+ )
+{
+ VOID *Hob;
+ MM_STATUS_CODE_USE_SERIAL *StatusCodeUseSerialHob;
+
+ Hob = GetFirstGuidHob (&gMmStatusCodeUseSerialHobGuid);
+ ASSERT (Hob != NULL);
+
+ StatusCodeUseSerialHob = (MM_STATUS_CODE_USE_SERIAL *)GET_GUID_HOB_DATA (Hob);
+
+ return StatusCodeUseSerialHob->StatusCodeUseSerial;
+}
/**
Entry point of Standalone MM Status Code Driver.
diff --git a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf
index d7c863b..618b7f8 100644
--- a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf
+++ b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf
@@ -35,6 +35,7 @@
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
[LibraryClasses]
SerialPortLib
@@ -46,16 +47,17 @@
DebugLib
MemoryAllocationLib
BaseMemoryLib
+ HobLib
[Guids]
gEfiStatusCodeDataTypeStringGuid ## SOMETIMES_CONSUMES ## UNDEFINED
gMemoryStatusCodeRecordGuid ## SOMETIMES_PRODUCES ## UNDEFINED # MmSystemTable
+ gMmStatusCodeUseSerialHobGuid ## CONSUMES
[Protocols]
gEfiMmRscHandlerProtocolGuid ## CONSUMES
[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize |128| gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES
diff --git a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c
index da49829..c30c02d 100644
--- a/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c
+++ b/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c
@@ -10,6 +10,23 @@
#include "StatusCodeHandlerMm.h"
/**
+ Check if the status code is using serial port.
+
+ This function determines whether the status code reporting mechanism
+ is configured to use the serial port.
+
+ @retval TRUE Status code is using the serial port.
+ @retval FALSE Status code is not using the serial port.
+**/
+BOOLEAN
+IsStatusCodeUsingSerialPort (
+ VOID
+ )
+{
+ return PcdGetBool (PcdStatusCodeUseSerial);
+}
+
+/**
Entry point of Traditional MM Status Code Driver.
This function is the entry point of Traditional MM Status Code Driver.
diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
index 4f937e2..eac1da5 100644
--- a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
+++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.c
@@ -66,7 +66,9 @@ PopulateHeaderAndCommunicate (
{
EFI_STATUS Status;
EFI_PEI_MM_COMMUNICATION_PPI *MmCommunicationPpi;
+ EFI_PEI_MM_COMMUNICATION3_PPI *MmCommunicationPpiV3;
EFI_MM_COMMUNICATE_HEADER *MmCommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *MmCommunicateHeaderV3;
SMM_VARIABLE_COMMUNICATE_HEADER *MmVarCommsHeader;
// Minimal sanity check
@@ -86,30 +88,67 @@ PopulateHeaderAndCommunicate (
goto Exit;
}
- Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, NULL, (VOID **)&MmCommunicationPpi);
+ MmCommunicationPpiV3 = NULL;
+ MmCommunicationPpi = NULL;
+
+ Status = PeiServicesLocatePpi (&gEfiPeiMmCommunication3PpiGuid, 0, NULL, (VOID **)&MmCommunicationPpiV3);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication PPI: %r\n", __func__, Status));
- goto Exit;
+ DEBUG ((DEBUG_WARN, "%a: Unable to locate PEI MM Communication3 PPI: %r\n", __func__, Status));
+ // Try to locate the older version of the PPI
+ Status = PeiServicesLocatePpi (&gEfiPeiMmCommunicationPpiGuid, 0, NULL, (VOID **)&MmCommunicationPpi);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to locate PEI MM Communication PPI: %r\n", __func__, Status));
+ goto Exit;
+ }
}
- // Zero the entire Communication Buffer Header
- MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommunicateBuffer;
+ if (MmCommunicationPpiV3 != NULL) {
+ // Zero the entire Communication Buffer Header
+ MmCommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommunicateBuffer;
- ZeroMem (MmCommunicateHeader, SMM_COMMUNICATE_HEADER_SIZE);
+ ZeroMem (MmCommunicateHeaderV3, SMM_COMMUNICATE_HEADER_SIZE_V3);
- // Use gEfiSmmVariableProtocolGuid to request the MM variable service in Standalone MM
- CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid, sizeof (GUID));
+ // Use gEfiSmmVariableProtocolGuid to request the MM variable service in Standalone MM
+ CopyMem ((VOID *)&MmCommunicateHeaderV3->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid, sizeof (GUID));
+ MmCommunicateHeaderV3->BufferSize = CommunicateBufferSize;
- // Program the MM header size
- MmCommunicateHeader->MessageLength = CommunicateBufferSize - SMM_COMMUNICATE_HEADER_SIZE;
+ CopyMem ((VOID *)&MmCommunicateHeaderV3->MessageGuid, &gEfiSmmVariableProtocolGuid, sizeof (GUID));
- MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE);
+ // Program the MM header size
+ MmCommunicateHeaderV3->MessageSize = CommunicateBufferSize - SMM_COMMUNICATE_HEADER_SIZE_V3;
- // We are only supporting GetVariable and GetNextVariableName
- MmVarCommsHeader->Function = Function;
+ MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)(MmCommunicateHeaderV3->MessageData);
+
+ // We are only supporting GetVariable and GetNextVariableName
+ MmVarCommsHeader->Function = Function;
+
+ // Send the MM request using MmCommunicationPei
+ Status = MmCommunicationPpiV3->Communicate (MmCommunicationPpiV3, CommunicateBuffer);
+ } else if (MmCommunicationPpi != NULL) {
+ // Zero the entire Communication Buffer Header
+ MmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommunicateBuffer;
+
+ ZeroMem (MmCommunicateHeader, SMM_COMMUNICATE_HEADER_SIZE);
+
+ // Use gEfiSmmVariableProtocolGuid to request the MM variable service in Standalone MM
+ CopyMem ((VOID *)&MmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid, sizeof (GUID));
+
+ // Program the MM header size
+ MmCommunicateHeader->MessageLength = CommunicateBufferSize - SMM_COMMUNICATE_HEADER_SIZE;
+
+ MmVarCommsHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)(CommunicateBuffer + SMM_COMMUNICATE_HEADER_SIZE);
+
+ // We are only supporting GetVariable and GetNextVariableName
+ MmVarCommsHeader->Function = Function;
+
+ // Send the MM request using MmCommunicationPei
+ Status = MmCommunicationPpi->Communicate (MmCommunicationPpi, CommunicateBuffer, &CommunicateBufferSize);
+ } else {
+ // We should never reach here, but just in case
+ Status = EFI_UNSUPPORTED;
+ DEBUG ((DEBUG_ERROR, "%a: No MM Communication PPI found!\n", __func__));
+ }
- // Send the MM request using MmCommunicationPei
- Status = MmCommunicationPpi->Communicate (MmCommunicationPpi, CommunicateBuffer, &CommunicateBufferSize);
if (EFI_ERROR (Status)) {
// Received an error from MM interface.
DEBUG ((DEBUG_ERROR, "%a - MM Interface Error: %r\n", __func__, Status));
diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
index 0feed8c..0b38329 100644
--- a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
+++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.h
@@ -23,6 +23,7 @@
#include <Ppi/ReadOnlyVariable2.h>
#include <Ppi/MmCommunication.h>
+#include <Ppi/MmCommunication3.h>
#include <Protocol/SmmVariable.h>
#include <Protocol/MmCommunication.h>
diff --git a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
index 13e8052..1f972db 100644
--- a/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
+++ b/MdeModulePkg/Universal/Variable/MmVariablePei/MmVariablePei.inf
@@ -34,7 +34,11 @@
[Ppis]
gEfiPeiReadOnlyVariable2PpiGuid ## PRODUCES
- gEfiPeiMmCommunicationPpiGuid ## CONSUMES
+ gEfiPeiMmCommunication3PpiGuid ## CONSUMES
+ gEfiPeiMmCommunicationPpiGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiMmCommunicateHeaderV3Guid
[Depex]
- gEfiPeiMmCommunicationPpiGuid
+ gEfiPeiMmCommunicationPpiGuid OR gEfiPeiMmCommunication3PpiGuid
diff --git a/MdeModulePkg/Universal/Variable/Pei/Variable.c b/MdeModulePkg/Universal/Variable/Pei/Variable.c
index 26f95c6..9f3d434 100644
--- a/MdeModulePkg/Universal/Variable/Pei/Variable.c
+++ b/MdeModulePkg/Universal/Variable/Pei/Variable.c
@@ -1336,6 +1336,7 @@ CalculateHobVariableCacheSize (
VARIABLE_STORE_HEADER *VariableStoreHeader;
VariableStoreHeader = NULL;
+ ZeroMem (&StoreInfo, sizeof (VARIABLE_STORE_INFO));
GetHobVariableStore (&StoreInfo, &VariableStoreHeader);
if (VariableStoreHeader == NULL) {
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h b/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h
index e7bd4c9..969a4f7 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/PrivilegePolymorphic.h
@@ -156,17 +156,13 @@ VariableSmmIsNonPrimaryBufferValid (
);
/**
- Whether the TCG or TCG2 protocols are installed in the UEFI protocol database.
- This information is used by the MorLock code to infer whether an existing
- MOR variable is legitimate or not.
-
- @retval TRUE Either the TCG or TCG2 protocol is installed in the UEFI
- protocol database
- @retval FALSE Neither the TCG nor the TCG2 protocol is installed in the UEFI
- protocol database
+ Whether the MOR variable is legitimate or not.
+
+ @retval TRUE MOR Variable is legitimate.
+ @retval FALSE MOR Variable in not legitimate.
**/
BOOLEAN
-VariableHaveTcgProtocols (
+VariableIsMorVariableLegitimate (
VOID
);
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
index 28e8cc5..7f8b2a7 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
@@ -475,7 +475,7 @@ MorLockInitAtEndOfDxe (
// can be deduced from the absence of the TCG / TCG2 protocols, as edk2's
// MOR implementation depends on (one of) those protocols.
//
- if (VariableHaveTcgProtocols ()) {
+ if (VariableIsMorVariableLegitimate ()) {
//
// The MOR variable originates from the platform firmware; set the MOR
// Control Lock variable to report the locking capability to the OS.
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
index 0dd72dd..984cae1 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
@@ -805,7 +805,6 @@ VariablePolicyVirtualAddressCallback (
The driver's entry point.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point executed successfully.
@retval other Some error occured when executing this entry point.
@@ -814,8 +813,7 @@ VariablePolicyVirtualAddressCallback (
EFI_STATUS
EFIAPI
VariablePolicySmmDxeMain (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+ IN EFI_HANDLE ImageHandle
)
{
EFI_STATUS Status;
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index f90ec70..b5e8bf6 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -84,7 +84,7 @@
gEfiVariableWriteArchProtocolGuid ## PRODUCES
gEfiVariableArchProtocolGuid ## PRODUCES
gEdkiiVariableLockProtocolGuid ## PRODUCES
- gEdkiiVariablePolicyProtocolGuid ## CONSUMES
+ gEdkiiVariablePolicyProtocolGuid ## PRODUCES
gEdkiiVarCheckProtocolGuid ## PRODUCES
[Guids]
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
index 5a03061..47f14c5 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
@@ -22,6 +22,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/VariableWrite.h>
#include <Protocol/Variable.h>
#include <Protocol/MmCommunication2.h>
+#include <Protocol/MmCommunication3.h>
#include <Protocol/SmmVariable.h>
#include <Protocol/VariableLock.h>
#include <Protocol/VarCheck.h>
@@ -48,6 +49,7 @@ EFI_HANDLE mHandle = NULL;
EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;
EFI_EVENT mVirtualAddressChangeEvent = NULL;
EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication2 = NULL;
+EFI_MM_COMMUNICATION3_PROTOCOL *mMmCommunication3 = NULL;
UINT8 *mVariableBuffer = NULL;
UINT8 *mVariableBufferPhysical = NULL;
VARIABLE_INFO_ENTRY *mVariableInfo = NULL;
@@ -67,8 +69,7 @@ BOOLEAN mIsRuntimeCacheEnabled = FALSE;
EFI_STATUS
EFIAPI
VariablePolicySmmDxeMain (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+ IN EFI_HANDLE ImageHandle
);
/**
@@ -164,17 +165,33 @@ InitCommunicateBuffer (
)
{
EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *SmmCommunicateHeaderV3;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
- if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
- return EFI_INVALID_PARAMETER;
- }
+ ZeroMem (mVariableBuffer, mVariableBufferSize);
+ if (mMmCommunication3 != NULL) {
+ if (DataSize + SMM_COMMUNICATE_HEADER_SIZE_V3 + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
+ return EFI_INVALID_PARAMETER;
+ }
- SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;
- CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
- SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
+ SmmCommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)mVariableBuffer;
+ CopyGuid (&SmmCommunicateHeaderV3->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid);
+ SmmCommunicateHeaderV3->BufferSize = mVariableBufferSize;
+ CopyGuid (&SmmCommunicateHeaderV3->MessageGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeaderV3->MessageSize = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeaderV3->MessageData;
+ } else {
+ // Use v1 communication header, if v3 protocol is not available.
+ if (DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE > mVariableBufferSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeader->MessageLength = DataSize + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
+ }
- SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
SmmVariableFunctionHeader->Function = Function;
if (DataPtr != NULL) {
*DataPtr = SmmVariableFunctionHeader->Data;
@@ -188,7 +205,7 @@ InitCommunicateBuffer (
@param[in] DataSize This size of the function header and the data.
- @retval EFI_SUCCESS Success is returned from the functin in SMM.
+ @retval EFI_SUCCESS Success is returned from the function in SMM.
@retval Others Failure is returned from the function in SMM.
**/
@@ -200,20 +217,38 @@ SendCommunicateBuffer (
EFI_STATUS Status;
UINTN CommSize;
EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *SmmCommunicateHeaderV3;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
- CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
- Status = mMmCommunication2->Communicate (
- mMmCommunication2,
+ if (mMmCommunication3 != NULL) {
+ Status = mMmCommunication3->Communicate (
+ mMmCommunication3,
mVariableBufferPhysical,
- mVariableBuffer,
- &CommSize
+ mVariableBuffer
);
- ASSERT_EFI_ERROR (Status);
+ ASSERT_EFI_ERROR (Status);
+
+ SmmCommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)mVariableBuffer;
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeaderV3->MessageData;
+
+ Status = SmmVariableFunctionHeader->ReturnStatus;
+ } else {
+ CommSize = DataSize + SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE;
+ Status = mMmCommunication2->Communicate (
+ mMmCommunication2,
+ mVariableBufferPhysical,
+ mVariableBuffer,
+ &CommSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
- SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mVariableBuffer;
- SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
- return SmmVariableFunctionHeader->ReturnStatus;
+ Status = SmmVariableFunctionHeader->ReturnStatus;
+ }
+
+ return Status;
}
/**
@@ -1343,7 +1378,12 @@ VariableAddressChangeEvent (
)
{
EfiConvertPointer (0x0, (VOID **)&mVariableBuffer);
- EfiConvertPointer (0x0, (VOID **)&mMmCommunication2);
+ if (mMmCommunication3 != NULL) {
+ EfiConvertPointer (0x0, (VOID **)&mMmCommunication3);
+ } else {
+ EfiConvertPointer (0x0, (VOID **)&mMmCommunication2);
+ }
+
EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRtCacheInfo.CacheInfoFlagBuffer);
EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRtCacheInfo.RuntimeHobCacheBuffer);
EfiConvertPointer (EFI_OPTIONAL_PTR, (VOID **)&mVariableRtCacheInfo.RuntimeNvCacheBuffer);
@@ -1368,6 +1408,7 @@ GetVariablePayloadSize (
EFI_STATUS Status;
SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *SmmGetPayloadSize;
EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *SmmCommunicateHeaderV3;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
UINTN CommSize;
UINT8 *CommBuffer;
@@ -1385,26 +1426,52 @@ GetVariablePayloadSize (
// Init the communicate buffer. The buffer data size is:
// SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
//
- CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
- CommBuffer = AllocateZeroPool (CommSize);
- if (CommBuffer == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
- CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
- SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
+ if (mMmCommunication3 != NULL) {
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE_V3 + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
+ CommBuffer = AllocateZeroPool (CommSize);
+ if (CommBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
- SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
- SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;
- SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *)SmmVariableFunctionHeader->Data;
+ SmmCommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer;
+ CopyGuid (&SmmCommunicateHeaderV3->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid);
+ SmmCommunicateHeaderV3->BufferSize = CommSize;
+ CopyGuid (&SmmCommunicateHeaderV3->MessageGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeaderV3->MessageSize = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeaderV3->MessageData;
- //
- // Send data to SMM.
- //
- Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
- ASSERT_EFI_ERROR (Status);
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;
+ SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *)SmmVariableFunctionHeader->Data;
+
+ //
+ // Send data to SMM.
+ //
+ Status = mMmCommunication3->Communicate (mMmCommunication3, CommBuffer, CommBuffer);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
+ CommBuffer = AllocateZeroPool (CommSize);
+ if (CommBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE);
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
+
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_PAYLOAD_SIZE;
+ SmmGetPayloadSize = (SMM_VARIABLE_COMMUNICATE_GET_PAYLOAD_SIZE *)SmmVariableFunctionHeader->Data;
+
+ //
+ // Send data to SMM.
+ //
+ Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
+ ASSERT_EFI_ERROR (Status);
+ }
Status = SmmVariableFunctionHeader->ReturnStatus;
if (EFI_ERROR (Status)) {
@@ -1450,6 +1517,7 @@ GetRuntimeCacheInfo (
EFI_STATUS Status;
SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *SmmGetRuntimeCacheInfo;
EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *SmmCommunicateHeaderV3;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
UINTN CommSize;
UINT8 *CommBuffer;
@@ -1467,22 +1535,44 @@ GetRuntimeCacheInfo (
AcquireLockOnlyAtBootTime (&mVariableServicesLock);
- CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);
- ZeroMem (CommBuffer, CommSize);
+ if (mMmCommunication3 != NULL) {
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE_V3 + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);
+ ZeroMem (CommBuffer, CommSize);
- SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
- CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
- SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);
+ SmmCommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer;
+ CopyGuid (&SmmCommunicateHeaderV3->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid);
+ SmmCommunicateHeaderV3->BufferSize = mVariableBufferSize;
+ CopyGuid (&SmmCommunicateHeaderV3->MessageGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeaderV3->MessageSize = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);
- SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
- SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO;
- SmmGetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *)SmmVariableFunctionHeader->Data;
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeaderV3->MessageData;
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO;
+ SmmGetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *)SmmVariableFunctionHeader->Data;
+
+ //
+ // Send data to SMM.
+ //
+ Status = mMmCommunication3->Communicate (mMmCommunication3, CommBuffer, CommBuffer);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);
+ ZeroMem (CommBuffer, CommSize);
+
+ SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO);
+
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_GET_RUNTIME_CACHE_INFO;
+ SmmGetRuntimeCacheInfo = (SMM_VARIABLE_COMMUNICATE_GET_RUNTIME_CACHE_INFO *)SmmVariableFunctionHeader->Data;
+
+ //
+ // Send data to SMM.
+ //
+ Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
+ ASSERT_EFI_ERROR (Status);
+ }
- //
- // Send data to SMM.
- //
- Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
- ASSERT_EFI_ERROR (Status);
if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
Status = EFI_BAD_BUFFER_SIZE;
goto Done;
@@ -1600,6 +1690,7 @@ SendRuntimeVariableCacheContextToSmm (
EFI_STATUS Status;
SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *SmmRuntimeVarCacheContext;
EFI_MM_COMMUNICATE_HEADER *SmmCommunicateHeader;
+ EFI_MM_COMMUNICATE_HEADER_V3 *SmmCommunicateHeaderV3;
SMM_VARIABLE_COMMUNICATE_HEADER *SmmVariableFunctionHeader;
UINTN CommSize;
UINT8 *CommBuffer;
@@ -1613,33 +1704,66 @@ SendRuntimeVariableCacheContextToSmm (
AcquireLockOnlyAtBootTime (&mVariableServicesLock);
- //
- // Init the communicate buffer. The buffer data size is:
- // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
- //
- CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
- ZeroMem (CommBuffer, CommSize);
+ if (mMmCommunication3 != NULL) {
+ //
+ // Init the communicate buffer. The buffer data size is:
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
+ //
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE_V3 + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
+ ZeroMem (CommBuffer, CommSize);
+
+ SmmCommunicateHeaderV3 = (EFI_MM_COMMUNICATE_HEADER_V3 *)CommBuffer;
+ CopyGuid (&SmmCommunicateHeaderV3->HeaderGuid, &gEfiMmCommunicateHeaderV3Guid);
+ SmmCommunicateHeaderV3->BufferSize = mVariableBufferSize;
+ CopyGuid (&SmmCommunicateHeaderV3->MessageGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeaderV3->MessageSize = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
+
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeaderV3->MessageData;
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT;
+ SmmRuntimeVarCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *)SmmVariableFunctionHeader->Data;
+
+ SmmRuntimeVarCacheContext->RuntimeHobCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer;
+ SmmRuntimeVarCacheContext->RuntimeVolatileCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer;
+ SmmRuntimeVarCacheContext->RuntimeNvCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer;
+ SmmRuntimeVarCacheContext->PendingUpdate = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->PendingUpdate;
+ SmmRuntimeVarCacheContext->ReadLock = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->ReadLock;
+ SmmRuntimeVarCacheContext->HobFlushComplete = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->HobFlushComplete;
+
+ //
+ // Send data to SMM.
+ //
+ Status = mMmCommunication3->Communicate (mMmCommunication3, CommBuffer, CommBuffer);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // Init the communicate buffer. The buffer data size is:
+ // SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
+ //
+ CommSize = SMM_COMMUNICATE_HEADER_SIZE + SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
+ ZeroMem (CommBuffer, CommSize);
- SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
- CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
- SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
+ SmmCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)CommBuffer;
+ CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid);
+ SmmCommunicateHeader->MessageLength = SMM_VARIABLE_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT);
- SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
- SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT;
- SmmRuntimeVarCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *)SmmVariableFunctionHeader->Data;
+ SmmVariableFunctionHeader = (SMM_VARIABLE_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
+ SmmVariableFunctionHeader->Function = SMM_VARIABLE_FUNCTION_INIT_RUNTIME_VARIABLE_CACHE_CONTEXT;
+ SmmRuntimeVarCacheContext = (SMM_VARIABLE_COMMUNICATE_RUNTIME_VARIABLE_CACHE_CONTEXT *)SmmVariableFunctionHeader->Data;
- SmmRuntimeVarCacheContext->RuntimeHobCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer;
- SmmRuntimeVarCacheContext->RuntimeVolatileCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer;
- SmmRuntimeVarCacheContext->RuntimeNvCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer;
- SmmRuntimeVarCacheContext->PendingUpdate = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->PendingUpdate;
- SmmRuntimeVarCacheContext->ReadLock = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->ReadLock;
- SmmRuntimeVarCacheContext->HobFlushComplete = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->HobFlushComplete;
+ SmmRuntimeVarCacheContext->RuntimeHobCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeHobCacheBuffer;
+ SmmRuntimeVarCacheContext->RuntimeVolatileCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeVolatileCacheBuffer;
+ SmmRuntimeVarCacheContext->RuntimeNvCache = (VARIABLE_STORE_HEADER *)(UINTN)mVariableRtCacheInfo.RuntimeNvCacheBuffer;
+ SmmRuntimeVarCacheContext->PendingUpdate = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->PendingUpdate;
+ SmmRuntimeVarCacheContext->ReadLock = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->ReadLock;
+ SmmRuntimeVarCacheContext->HobFlushComplete = &((CACHE_INFO_FLAG *)(UINTN)mVariableRtCacheInfo.CacheInfoFlagBuffer)->HobFlushComplete;
+
+ //
+ // Send data to SMM.
+ //
+ Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
+ ASSERT_EFI_ERROR (Status);
+ }
- //
- // Send data to SMM.
- //
- Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
- ASSERT_EFI_ERROR (Status);
if (CommSize <= SMM_VARIABLE_COMMUNICATE_HEADER_SIZE) {
Status = EFI_BAD_BUFFER_SIZE;
goto Done;
@@ -1670,6 +1794,7 @@ SmmVariableReady (
)
{
EFI_STATUS Status;
+ EFI_HANDLE VariablePolicyHandle;
EFI_HOB_GUID_TYPE *GuidHob;
Status = gBS->LocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID **)&mSmmVariable);
@@ -1677,7 +1802,12 @@ SmmVariableReady (
return;
}
- Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);
+ Status = gBS->LocateProtocol (&gEfiMmCommunication3ProtocolGuid, NULL, (VOID **)&mMmCommunication3);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "Unable to locate MM communication v3 (%r). Falling back to v2\n", Status));
+ Status = gBS->LocateProtocol (&gEfiMmCommunication2ProtocolGuid, NULL, (VOID **)&mMmCommunication2);
+ }
+
ASSERT_EFI_ERROR (Status);
//
@@ -1721,6 +1851,16 @@ SmmVariableReady (
gRT->SetVariable = RuntimeServiceSetVariable;
gRT->QueryVariableInfo = RuntimeServiceQueryVariableInfo;
+ VariablePolicyHandle = (Context != NULL) ? Context : mHandle;
+ if (Context == NULL) {
+ DEBUG ((DEBUG_WARN, "Variable policy protocol was not installed on the variable image handle.\n"));
+ }
+
+ //
+ // Initialize the Variable Policy protocol and engine.
+ //
+ VariablePolicySmmDxeMain (VariablePolicyHandle);
+
//
// Install the Variable Architectural Protocol on a new handle.
//
@@ -1831,7 +1971,7 @@ VariableSmmRuntimeInitialize (
&gEfiSmmVariableProtocolGuid,
TPL_CALLBACK,
SmmVariableReady,
- NULL,
+ ImageHandle,
&SmmVariableRegistration
);
@@ -1891,8 +2031,5 @@ VariableSmmRuntimeInitialize (
&mVirtualAddressChangeEvent
);
- // Initialize the VariablePolicy protocol and engine.
- VariablePolicySmmDxeMain (ImageHandle, SystemTable);
-
return EFI_SUCCESS;
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
index d984a36..af8a32a 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
@@ -66,6 +66,7 @@
gEfiVariableWriteArchProtocolGuid ## PRODUCES
gEfiVariableArchProtocolGuid ## PRODUCES
gEfiMmCommunication2ProtocolGuid ## CONSUMES
+ gEfiMmCommunication3ProtocolGuid ## CONSUMES
## CONSUMES
## NOTIFY
## UNDEFINED # Used to do smm communication
@@ -113,9 +114,10 @@
gEfiEndOfDxeEventGroupGuid
gEfiDeviceSignatureDatabaseGuid
gEdkiiVariableRuntimeCacheInfoHobGuid
+ gEfiMmCommunicateHeaderV3Guid
[Depex]
- gEfiMmCommunication2ProtocolGuid
+ gEfiMmCommunication2ProtocolGuid OR gEfiMmCommunication3ProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
VariableSmmRuntimeDxeExtra.uni
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c
index 1b9cf6d..1057822 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.c
@@ -7,6 +7,8 @@ Copyright (c) 2018, Linaro, Ltd. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
+
+#include <Library/MmServicesTableLib.h>
#include <Library/StandaloneMmMemLib.h>
#include "Variable.h"
@@ -67,6 +69,17 @@ VariableNotifySmmWriteReady (
VOID
)
{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+ Status = gMmst->MmInstallProtocolInterface (
+ &Handle,
+ &gSmmVariableWriteGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
}
/**
@@ -89,19 +102,15 @@ VariableServiceInitialize (
}
/**
- Whether the TCG or TCG2 protocols are installed in the UEFI protocol database.
- This information is used by the MorLock code to infer whether an existing
- MOR variable is legitimate or not.
-
- @retval TRUE Either the TCG or TCG2 protocol is installed in the UEFI
- protocol database
- @retval FALSE Neither the TCG nor the TCG2 protocol is installed in the UEFI
- protocol database
+ Whether the MOR variable is legitimate or not.
+
+ @retval TRUE MOR Variable is legitimate.
+ @retval FALSE MOR Variable in not legitimate.
**/
BOOLEAN
-VariableHaveTcgProtocols (
+VariableIsMorVariableLegitimate (
VOID
)
{
- return FALSE;
+ return TRUE;
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
index c418571..2d651c3 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -115,6 +115,7 @@
gEfiMemoryOverwriteControlDataGuid ## SOMETIMES_CONSUMES ## Variable:L"MemoryOverwriteRequestControl"
gEfiMemoryOverwriteRequestControlLockGuid ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControlLock"
+ gSmmVariableWriteGuid ## PRODUCES ## GUID # Install protocol
gEfiSystemNvDataFvGuid ## CONSUMES ## GUID
gEdkiiFaultTolerantWriteGuid ## SOMETIMES_CONSUMES ## HOB
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c
index 7247f75..cd82bb5 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableTraditionalMm.c
@@ -118,12 +118,12 @@ VariableServiceInitialize (
MOR variable is legitimate or not.
@retval TRUE Either the TCG or TCG2 protocol is installed in the UEFI
- protocol database
+ protocol database. MOR variable is legitimate.
@retval FALSE Neither the TCG nor the TCG2 protocol is installed in the UEFI
- protocol database
+ protocol database. MOR variable is not legitimate.
**/
BOOLEAN
-VariableHaveTcgProtocols (
+VariableIsMorVariableLegitimate (
VOID
)
{