From 00de3481df4115df6bd8b80cc28d651a5984b143 Mon Sep 17 00:00:00 2001 From: Mike Ebersol Date: Mon, 4 May 2026 22:17:43 +0000 Subject: [PATCH 1/2] Merged PR 15395385: [Copilot] ARM64: Add Hash2DxeCrypto for TLS support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Why is this change being made?**\n\nBug #60149538 — ARM64 Hyper-V UEFI does not support HTTP/TLS protocols. The original X64 HTTP/TLS enablement (PR 6741249, Dec 2021) added `Hash2CryptoLib` and `Hash2DxeCrypto` alongside the HTTP/DNS/TLS modules. When ARM64 HTTP/TLS support was added (PR 14243873, Nov 2025), these two Hash2 entries were missed. Without `Hash2DxeCrypto`, the `EFI_HASH2_PROTOCOL` is not available, which TLS needs for certificate hash verification — causing HTTPS connections to fail on ARM64 VMs.\n\n**What changed?**\n\nAdded the missing `Hash2CryptoLib` library class and `Hash2DxeCrypto` component to `MsvmPkgAARCH64.dsc` and `MsvmPkgAARCH64.fdf`, matching what X64 already has.\n\n**How was the change tested?**\n\nBuild verification needed. Partner (CBMR team) should re-test ARM64 HTTPS/TLS scenarios. ---- New feature addition to enable HTTP/TLS protocol support for ARM64 architecture by integrating cryptographic hashing capabilities. This pull request adds Hash2DxeCrypto driver support to the ARM64 UEFI build, bringing TLS/HTTPS protocol capabilities to ARM64 Hyper-V that were previously only available on x64. This change addresses the linked work item by providing the necessary cryptographic components for secure network protocols. - `MsvmPkgAARCH64.dsc`: Added `Hash2DxeCrypto.inf` to security components section and registered `Hash2CryptoLib` library dependency - `MsvmPkgAARCH64.fdf`: Included `Hash2DxeCrypto` driver in the firmware image build Related work items: #60149538 --- MsvmPkg/MsvmPkgAARCH64.dsc | 1954 ++++++++++++++++++------------------ MsvmPkg/MsvmPkgAARCH64.fdf | 774 +++++++------- 2 files changed, 1367 insertions(+), 1361 deletions(-) diff --git a/MsvmPkg/MsvmPkgAARCH64.dsc b/MsvmPkg/MsvmPkgAARCH64.dsc index a4ee8da46..8c217cbc8 100644 --- a/MsvmPkg/MsvmPkgAARCH64.dsc +++ b/MsvmPkg/MsvmPkgAARCH64.dsc @@ -1,189 +1,190 @@ -## @file -# EFI/Framework Microsoft Virtual Machine Firmware (MSVM) platform -# -# Copyright (c) Microsoft. -# SPDX-License-Identifier: BSD-2-Clause-Patent -# -## - -################################################################################ -# -# Defines Section - statements that will be processed to create a Makefile. -# -################################################################################ -[Defines] - PLATFORM_NAME = Msvm - PLATFORM_GUID = 60d3fbae-b4ed-4a10-9145-f8185dd8b1bd - PLATFORM_VERSION = 0.1 - DSC_SPECIFICATION = 0x00010005 - OUTPUT_DIRECTORY = Build/MsvmAARCH64 - SUPPORTED_ARCHITECTURES = AARCH64 - BUILD_TARGETS = DEBUG|RELEASE - SKUID_IDENTIFIER = DEFAULT - FLASH_DEFINITION = MsvmPkg/MsvmPkgAARCH64.fdf - -# -# Defines for the pre-built BaseCryptLib -# - PEI_CRYPTO_SERVICES = TINY_SHA - DXE_CRYPTO_SERVICES = ALL - PEI_CRYPTO_ARCH = AARCH64 - DXE_CRYPTO_ARCH = AARCH64 - -################################################################################ -# +## @file +# EFI/Framework Microsoft Virtual Machine Firmware (MSVM) platform +# +# Copyright (c) Microsoft. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = Msvm + PLATFORM_GUID = 60d3fbae-b4ed-4a10-9145-f8185dd8b1bd + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/MsvmAARCH64 + SUPPORTED_ARCHITECTURES = AARCH64 + BUILD_TARGETS = DEBUG|RELEASE + SKUID_IDENTIFIER = DEFAULT + FLASH_DEFINITION = MsvmPkg/MsvmPkgAARCH64.fdf + +# +# Defines for the pre-built BaseCryptLib +# + PEI_CRYPTO_SERVICES = TINY_SHA + DXE_CRYPTO_SERVICES = ALL + PEI_CRYPTO_ARCH = AARCH64 + DXE_CRYPTO_ARCH = AARCH64 + +################################################################################ +# # BuildOptions Section - extra build flags -# TODO: There should be only one [BuildOptions]. -# -################################################################################ -[BuildOptions] +# TODO: There should be only one [BuildOptions]. +# +################################################################################ +[BuildOptions] *_*_*_GENFW_FLAGS = --keepexceptiontable *_*_*_CC_FLAGS = -D MS_HYP_CHANGE_BEGIN -D MS_HYP_CHANGE -D MS_HYP -D MU_CHANGE - DEBUG_*_*_CC_FLAGS = -D DEBUG_PLATFORM + DEBUG_*_*_CC_FLAGS = -D DEBUG_PLATFORM *_GCC_*_ASLDLINK_FLAGS = -z common-page-size=0x1000 *_GCC_*_DLINK_FLAGS = -z common-page-size=0x1000 - - # Workaround https://github.com/tianocore/edk2/pull/11535/changes/38760819a84de03127e0d93abd238eee2ce7a6e8 - # BaseTools/Conf: Make ASLCC_FLAGS independent of CC_FLAGS - # GenFW:ConvertELF fails otherwise. - # Ideal, but does not work: *_GCC_AARCH64_ASLCC_FLAGS = $(GCC_AARCH64_CC_FLAGS) - *_GCC_AARCH64_ASLCC_FLAGS = -mlittle-endian -fno-short-enums -fverbose-asm -funsigned-char -ffunction-sections -fdata-sections -Wno-address -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-pic -fno-pie -ffixed-x18 -mstack-protector-guard=global - -# ARM64 has a UEFI spec requirement that RuntimeServiceCode/Data is 64K aligned + + # Workaround https://github.com/tianocore/edk2/pull/11535/changes/38760819a84de03127e0d93abd238eee2ce7a6e8 + # BaseTools/Conf: Make ASLCC_FLAGS independent of CC_FLAGS + # GenFW:ConvertELF fails otherwise. + # Ideal, but does not work: *_GCC_AARCH64_ASLCC_FLAGS = $(GCC_AARCH64_CC_FLAGS) + *_GCC_AARCH64_ASLCC_FLAGS = -mlittle-endian -fno-short-enums -fverbose-asm -funsigned-char -ffunction-sections -fdata-sections -Wno-address -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-pic -fno-pie -ffixed-x18 -mstack-protector-guard=global + +# ARM64 has a UEFI spec requirement that RuntimeServiceCode/Data is 64K aligned # This applies to in-memory section alignment, and need not apply to file system alignment. -[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] +[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] MSFT:*_*_AARCH64_DLINK_FLAGS = -align:0x10000 *_CLANGPDB_AARCH64_DLINK_FLAGS = -align:0x10000 *_GCC_AARCH64_ASLDLINK_FLAGS = -z common-page-size=0x10000 *_GCC_AARCH64_DLINK_FLAGS = -z common-page-size=0x10000 - -[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.PEIM, BuildOptions.common.EDKII.PEI_CORE] + +[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.PEIM, BuildOptions.common.EDKII.PEI_CORE] MSFT:*_*_*_DLINK_FLAGS = -align:4096 -filealign:4096 *_CLANGPDB_*_DLINK_FLAGS = -align:4096 -filealign:4096 - -################################################################################ -# -# SKU Identification section - list of all SKU IDs supported by this Platform. -# -################################################################################ -[SkuIds] - 0|DEFAULT - -################################################################################ -# -# Library Class section -# -# Library class names used by this platform and the implementations of those -# libraries. | -# -################################################################################ - -# -# Library instances to use by default for all modules and phases unless overridden below -# -[LibraryClasses] - AdvancedLoggerAccessLib|AdvLoggerPkg/Library/AdvancedLoggerAccessLib/AdvancedLoggerAccessLib.inf - AdvancedLoggerHdwPortLib|AdvLoggerPkg/Library/AdvancedLoggerHdwPortLib/AdvancedLoggerHdwPortLib.inf - ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf - ArmMmuLib|UefiCpuPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf - ArmMonitorLib|ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf - ArmSmcLib|MdePkg/Library/ArmSmcLib/ArmSmcLib.inf - ArmTrngLib|MdePkg/Library/BaseArmTrngLibNull/BaseArmTrngLibNull.inf - AssertLib|AdvLoggerPkg/Library/AssertLib/AssertLib.inf - BaseLib|MdePkg/Library/BaseLib/BaseLib.inf - BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf - BiosDeviceLib|MsvmPkg/Library/BiosDeviceLib/BiosDeviceLib.inf - CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf - CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf - CrashLib|MsvmPkg/Library/CrashLib/CrashLib.inf - CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf - CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf - DebugLib|AdvLoggerPkg/Library/BaseDebugLibAdvancedLogger/BaseDebugLibAdvancedLogger.inf - DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf - DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf - DefaultExceptionHandlerLib|MsvmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf - DeviceStateLib|MdeModulePkg/Library/DeviceStateLib/DeviceStateLib.inf - DisplayDeviceStateLib|MsGraphicsPkg/Library/ColorBarDisplayDeviceStateLib/ColorBarDisplayDeviceStateLib.inf - EmclLib|MsvmPkg/Library/EmclLib/EmclLib.inf - FltUsedLib|MsCorePkg/Library/FltUsedLib/FltUsedLib.inf - FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf - HwResetSystemLib|ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf - ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf - IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf - IsolationLib|MsvmPkg/Library/IsolationLib/IsolationLib.inf - MathLib|MsCorePkg/Library/MathLib/MathLib.inf - MmuLib|ArmPkg/Library/MmuLib/BaseMmuLib.inf - MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf - MsBaseLib|MsvmPkg/Library/MsBaseLib/MsBaseLib.inf - MsBootPolicyLib|MsvmPkg/Library/MsBootPolicyLib/MsBootPolicyLib.inf - OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf - PanicLib|MdePkg/Library/BasePanicLibNull/BasePanicLibNull.inf - PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf - PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf - PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf - PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf - PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf - PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf - PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf - RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf - ResetUtilityLib|MdeModulePkg/Library/ResetUtilityLib/ResetUtilityLib.inf - SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf - StackCheckFailureHookLib|MdePkg/Library/StackCheckFailureHookLibNull/StackCheckFailureHookLibNull.inf - StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf - SecurityLockAuditLib|MdeModulePkg/Library/SecurityLockAuditDebugMessageLib/SecurityLockAuditDebugMessageLib.inf ##MSCHANGE - SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf - SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf - Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf - Tpm2HelpLib|SecurityPkg/Library/Tpm2HelpLib/Tpm2HelpLib.inf - TimerLib|MsvmPkg/Library/HvTimerLib/HvTimerLib.inf - UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf - UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf - UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf - UiRectangleLib|MsGraphicsPkg/Library/BaseUiRectangleLib/BaseUiRectangleLib.inf - VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf - -!if $(DEBUGLIB_SERIAL) == 1 - SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf - PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf -!endif - - ## MS_CHANGE_? - # MeasuredBoot and Other TPM-Based Security - Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf - Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf - TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf - Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf - Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf - OemTpm2InitLib|SecurityPkg/Library/OemTpm2InitLibNull/OemTpm2InitLib.inf ## MS_CHANGE_? - Tcg2PreUefiEventLogLib|SecurityPkg/Library/Tcg2PreUefiEventLogLibNull/Tcg2PreUefiEventLogLibNull.inf - ## MS_CHANGE_? - - # MsCore BDS & FrontPage Libs - PlatformBootManagerLib|MsCorePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf - DeviceBootManagerLib|MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.inf - UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf - MsLogoLib|MsvmPkg/Library/MsLogoLib/MsLogoLib.inf #point to MsLogoLib - BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf - SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf - MsPlatBdsLib|MsvmPkg/Library/MsPlatBdsLib/MsPlatBdsLib.inf - - # - # MsGraphicsPkg Libs - # - UIToolKitLib|MsGraphicsPkg/Library/SimpleUIToolKit/SimpleUIToolKit.inf - MsColorTableLib|MsGraphicsPkg/Library/MsColorTableLib/MsColorTableLib.inf - MsUiThemeCopyLib|MsGraphicsPkg/Library/MsUiThemeCopyLib/MsUiThemeCopyLib.inf - PlatformThemeLib|MsvmPkg/Library/PlatformThemeLib/PlatformThemeLib.inf - SwmDialogsLib|MsGraphicsPkg/Library/SwmDialogsLib/SwmDialogs.inf - - MsUiThemeLib|MsGraphicsPkg/Library/MsUiThemeLib/Dxe/MsUiThemeLib.inf - - # - # Platform Runtime Package (PRM) Libs - # - PrmContextBufferLib|PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf - PrmModuleDiscoveryLib|PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf - PrmPeCoffLib|PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf + +################################################################################ +# +# SKU Identification section - list of all SKU IDs supported by this Platform. +# +################################################################################ +[SkuIds] + 0|DEFAULT + +################################################################################ +# +# Library Class section +# +# Library class names used by this platform and the implementations of those +# libraries. | +# +################################################################################ + +# +# Library instances to use by default for all modules and phases unless overridden below +# +[LibraryClasses] + AdvancedLoggerAccessLib|AdvLoggerPkg/Library/AdvancedLoggerAccessLib/AdvancedLoggerAccessLib.inf + AdvancedLoggerHdwPortLib|AdvLoggerPkg/Library/AdvancedLoggerHdwPortLib/AdvancedLoggerHdwPortLib.inf + ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf + ArmMmuLib|UefiCpuPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf + ArmMonitorLib|ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf + ArmSmcLib|MdePkg/Library/ArmSmcLib/ArmSmcLib.inf + ArmTrngLib|MdePkg/Library/BaseArmTrngLibNull/BaseArmTrngLibNull.inf + AssertLib|AdvLoggerPkg/Library/AssertLib/AssertLib.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf + BiosDeviceLib|MsvmPkg/Library/BiosDeviceLib/BiosDeviceLib.inf + CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + CrashLib|MsvmPkg/Library/CrashLib/CrashLib.inf + CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf + CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf + DebugLib|AdvLoggerPkg/Library/BaseDebugLibAdvancedLogger/BaseDebugLibAdvancedLogger.inf + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + DefaultExceptionHandlerLib|MsvmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf + DeviceStateLib|MdeModulePkg/Library/DeviceStateLib/DeviceStateLib.inf + DisplayDeviceStateLib|MsGraphicsPkg/Library/ColorBarDisplayDeviceStateLib/ColorBarDisplayDeviceStateLib.inf + EmclLib|MsvmPkg/Library/EmclLib/EmclLib.inf + FltUsedLib|MsCorePkg/Library/FltUsedLib/FltUsedLib.inf + FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf + Hash2CryptoLib|SecurityPkg/Library/DxeHash2CryptoLib/DxeHash2CryptoLib.inf + HwResetSystemLib|ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf + ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf + IsolationLib|MsvmPkg/Library/IsolationLib/IsolationLib.inf + MathLib|MsCorePkg/Library/MathLib/MathLib.inf + MmuLib|ArmPkg/Library/MmuLib/BaseMmuLib.inf + MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf + MsBaseLib|MsvmPkg/Library/MsBaseLib/MsBaseLib.inf + MsBootPolicyLib|MsvmPkg/Library/MsBootPolicyLib/MsBootPolicyLib.inf + OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf + PanicLib|MdePkg/Library/BasePanicLibNull/BasePanicLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf + PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf + PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf + PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf + PlatformPeiLib|ArmPlatformPkg/PlatformPei/PlatformPeiLib.inf + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf + ResetUtilityLib|MdeModulePkg/Library/ResetUtilityLib/ResetUtilityLib.inf + SortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf + StackCheckFailureHookLib|MdePkg/Library/StackCheckFailureHookLibNull/StackCheckFailureHookLibNull.inf + StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf + SecurityLockAuditLib|MdeModulePkg/Library/SecurityLockAuditDebugMessageLib/SecurityLockAuditDebugMessageLib.inf ##MSCHANGE + SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + Tpm2HelpLib|SecurityPkg/Library/Tpm2HelpLib/Tpm2HelpLib.inf + TimerLib|MsvmPkg/Library/HvTimerLib/HvTimerLib.inf + UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf + UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + UiRectangleLib|MsGraphicsPkg/Library/BaseUiRectangleLib/BaseUiRectangleLib.inf + VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf + +!if $(DEBUGLIB_SERIAL) == 1 + SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf + PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf +!endif + + ## MS_CHANGE_? + # MeasuredBoot and Other TPM-Based Security + Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf + Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + Tcg2PhysicalPresenceLib|SecurityPkg/Library/DxeTcg2PhysicalPresenceLib/DxeTcg2PhysicalPresenceLib.inf + Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf + OemTpm2InitLib|SecurityPkg/Library/OemTpm2InitLibNull/OemTpm2InitLib.inf ## MS_CHANGE_? + Tcg2PreUefiEventLogLib|SecurityPkg/Library/Tcg2PreUefiEventLogLibNull/Tcg2PreUefiEventLogLibNull.inf + ## MS_CHANGE_? + + # MsCore BDS & FrontPage Libs + PlatformBootManagerLib|MsCorePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf + DeviceBootManagerLib|MsvmPkg/Library/DeviceBootManagerLib/DeviceBootManagerLib.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + MsLogoLib|MsvmPkg/Library/MsLogoLib/MsLogoLib.inf #point to MsLogoLib + BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf + MsPlatBdsLib|MsvmPkg/Library/MsPlatBdsLib/MsPlatBdsLib.inf + + # + # MsGraphicsPkg Libs + # + UIToolKitLib|MsGraphicsPkg/Library/SimpleUIToolKit/SimpleUIToolKit.inf + MsColorTableLib|MsGraphicsPkg/Library/MsColorTableLib/MsColorTableLib.inf + MsUiThemeCopyLib|MsGraphicsPkg/Library/MsUiThemeCopyLib/MsUiThemeCopyLib.inf + PlatformThemeLib|MsvmPkg/Library/PlatformThemeLib/PlatformThemeLib.inf + SwmDialogsLib|MsGraphicsPkg/Library/SwmDialogsLib/SwmDialogs.inf + + MsUiThemeLib|MsGraphicsPkg/Library/MsUiThemeLib/Dxe/MsUiThemeLib.inf + + # + # Platform Runtime Package (PRM) Libs + # + PrmContextBufferLib|PrmPkg/Library/DxePrmContextBufferLib/DxePrmContextBufferLib.inf + PrmModuleDiscoveryLib|PrmPkg/Library/DxePrmModuleDiscoveryLib/DxePrmModuleDiscoveryLib.inf + PrmPeCoffLib|PrmPkg/Library/DxePrmPeCoffLib/DxePrmPeCoffLib.inf # memcpy and memset are difficult to avoid, esp. on ARM64. # e.g. struct/union/array init/assign, passing va_list by value in PrintLib. @@ -191,816 +192,819 @@ # Current upstream AMD64 CompilerIntrinsicsLib does not compile but future does. [LibraryClasses.AARCH64] NULL|MdePkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf - -# -# Library instance overrides for SEC and PEI -# -[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM] - ArmMmuLib|UefiCpuPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf - ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf - MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf - PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf - PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf - StackCheckLib|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf - -# -# Library instance overrides just for SEC -# -[LibraryClasses.common.SEC] - DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf - -# -# Library instance overrides for PEI -# -[LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM] - FrameBufferMemDrawLib|MsGraphicsPkg/Library/FrameBufferMemDrawLib/FrameBufferMemDrawLibPei.inf - HvHypercallLib|MsvmPkg/Library/HvHypercallLib/PeiHvHypercallLib.inf - HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf - OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf - ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf - PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf - WatchdogTimerLib|MsvmPkg/Library/WatchdogTimerLib/WatchdogTimerLib.inf - ResetSystemLib|MdeModulePkg/Library/PeiResetSystemLib/PeiResetSystemLib.inf - -# -# Library instance overrides just for PEI CORE -# -[LibraryClasses.common.PEI_CORE] - AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/PeiCore/AdvancedLoggerLib.inf - PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf - -# -# Library instance overrides just for PEIMs -# -[LibraryClasses.common.PEIM] - AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/Pei/AdvancedLoggerLib.inf - DebugLib|AdvLoggerPkg/Library/PeiDebugLibAdvancedLogger/PeiDebugLibAdvancedLogger.inf - PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf - ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf - PcdDatabaseLoaderLib|MdeModulePkg/Library/PcdDatabaseLoaderLib/Pei/PcdDatabaseLoaderLibPei.inf # MU_CHANGE - RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf - - MsUiThemeLib|MsGraphicsPkg/Library/MsUiThemeLib/Pei/MsUiThemeLib.inf - - -# -# Library instance overrides for DXE -# -[LibraryClasses.common.DXE_CORE, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION] - BootEventLogLib|MsvmPkg/Library/BootEventLogLib/BootEventLogLib.inf - ConfigLib|MsvmPkg/Library/ConfigLib/ConfigLib.inf - DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf - DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf - DxeMemoryProtectionHobLib|MdeModulePkg/Library/MemoryProtectionHobLibNull/DxeMemoryProtectionHobLibNull.inf - DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf - DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf - EventLogLib|MsvmPkg/Library/EventLogLib/EventLogLib.inf - ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf - FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf - FrameBufferMemDrawLib|MsGraphicsPkg/Library/FrameBufferMemDrawLib/FrameBufferMemDrawLibDxe.inf - HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf - HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf - HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf - IpIoLib|NetworkPkg/Library/DxeIpIoLib/DxeIpIoLib.inf - MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf - MemoryTypeInformationChangeLib|MdeModulePkg/Library/MemoryTypeInformationChangeLibNull/MemoryTypeInformationChangeLibNull.inf - MmioAllocationLib|MsvmPkg/Library/MmioAllocationLib/MmioAllocationLib.inf - NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf - PcdDatabaseLoaderLib|MdeModulePkg/Library/PcdDatabaseLoaderLib/Dxe/PcdDatabaseLoaderLibDxe.inf # MU_CHANGE - PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf - ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf - ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf - RngLib|MsvmPkg/Library/MsvmRngLib/MsvmRngLib.inf - SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf - UdpIoLib|NetworkPkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf - UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf - UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf - UefiLib|MdePkg/Library/UefiLib/UefiLib.inf - UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf - WatchdogTimerLib|MsvmPkg/Library/WatchdogTimerLib/WatchdogTimerLib.inf - PciSegmentLib|MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf - PciSegmentInfoLib|MsvmPkg/Library/PciSegmentInfoLib/PciSegmentInfoLib.inf - IoMmuLib|MdeModulePkg/Library/IoMmuLibNull/IoMmuLibNull.inf - -# -# Library instances overrides for just DXE CORE -# -[LibraryClasses.common.DXE_CORE] - AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/DxeCore/AdvancedLoggerLib.inf - DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf - HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf - MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf - HvHypercallLib|MsvmPkg/Library/HvHypercallLib/HvHypercallLib.inf -##MSChange Begin -[LibraryClasses.common.DXE_DRIVER] - ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf - HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf - PolicyLib|PolicyServicePkg/Library/DxePolicyLib/DxePolicyLib.inf -##MSChange End - Tcg2PhysicalPresencePromptLib|MsvmPkg/Library/Tcg2PhysicalPresencePromptLibApprove/Tcg2PhysicalPresencePromptLibApprove.inf ## MS_CHANGE - PciHostBridgeLib|MsvmPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf - -# -# Library instance overrides for all DXE Drivers -# -[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER] - HvHypercallLib|MsvmPkg/Library/HvHypercallLib/HvHypercallLib.inf - UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf - -# -# Library instance overrides for DXE Drivers and Applications -# -[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION] - AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/Dxe/AdvancedLoggerLib.inf - -# -# Library instance overrides for just DXE Runtime Drivers -# -[LibraryClasses.common.DXE_RUNTIME_DRIVER] - AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/Runtime/AdvancedLoggerLib.inf - BiosDeviceLib|MsvmPkg/Library/BiosDeviceLib/BiosDeviceRuntimeLib.inf - # runtime drivers shouldn't use UEFI debugging, especially after ExitBootServices() - DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf - ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf - ResetSystemLib|MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.inf - UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf - -# PERF MODULES START -!if $(PERF_TRACE_ENABLE) == TRUE -[PcdsFixedAtBuild] - # Sets bits 0, 3 to enable measurement but skip binding supports - gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x9 - # 16M should be enough to fit all the verbose measurements - gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize|0x1000000 - -[LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM] - PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf - -[LibraryClasses.common.UEFI_APPLICATION, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER] - PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf - -[LibraryClasses.common.DXE_CORE] - PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf - -# [Components.common] -# # FBPT Dump App: -# # Note, this has a dependency on ShellLib, so can only build this if also building the shell -# PerformancePkg/Application/FbptDump/FbptDump.inf -!else -[LibraryClasses.common] - PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf -!endif -# PERF MODULES END - -[PcdsFixedAtBuild.common] - # Advanced Logger Config - gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerPreMemPages|1 # Size is 4KB - gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerPages|1024 # Size is 4MB -!if $(DEBUGLIB_SERIAL) == 1 - !ifdef DEBUG_NOISY - # This enables verbose output - gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerHdwPortDebugPrintErrorLevel|0x804FEF4B - !else - # This default turns on errors and warnings - gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerHdwPortDebugPrintErrorLevel|0x80000002 - !endif -!else - # We do not want anything out of serial if the flag is not provided - gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerHdwPortDebugPrintErrorLevel|0x0 -!endif - - # Feature Debugger Config - DebuggerFeaturePkgTokenSpaceGuid.PcdInitialBreakpointTimeoutMs|0 -!if $(DEBUGGER_ENABLED) == 1 - DebuggerFeaturePkgTokenSpaceGuid.PcdForceEnableDebugger|TRUE -!endif - - # Synthetic Timer Config - gMsvmPkgTokenSpaceGuid.PcdSynicTimerSintIndex|0x1 - gMsvmPkgTokenSpaceGuid.PcdSynicTimerTimerIndex|0x0 - gMsvmPkgTokenSpaceGuid.PcdSynicTimerVector|17 # use PPI for SINTs - gMsvmPkgTokenSpaceGuid.PcdSynicTimerDefaultPeriod|100000 - - # Vmbus Config - gMsvmPkgTokenSpaceGuid.PcdVmbusSintVector|18 # use PPI for SINTs - gMsvmPkgTokenSpaceGuid.PcdVmbusSintIndex|0x2 - # PPI for Linux. Older public kernels used by WSL2 had 16 and 17 hardcoded, so - # use the next available, 18. - gMsvmPkgTokenSpaceGuid.PcdVmbusVector|18 - - # BIOS Device - gMsvmPkgTokenSpaceGuid.PcdBiosBaseAddress|0xEFFED000 - - # Generation Counter Device - gMsvmPkgTokenSpaceGuid.PcdGenCountEventVector|35 # SPI - - # Battery Device - gMsvmPkgTokenSpaceGuid.PcdBatteryBase|0xEFFEA000 - gMsvmPkgTokenSpaceGuid.PcdBatteryEventVector|36 # SPI - - # UART Devices - gMsvmPkgTokenSpaceGuid.PcdCom1RegisterBase|0xEFFEC000 - gMsvmPkgTokenSpaceGuid.PcdCom1Vector|33 # SPI - gMsvmPkgTokenSpaceGuid.PcdCom2RegisterBase|0xEFFEB000 - gMsvmPkgTokenSpaceGuid.PcdCom2Vector|34 # SPI - - # RTC (clock) - gMsvmPkgTokenSpaceGuid.PcdRtcRegisterBase|0x70 - gMsvmPkgTokenSpaceGuid.PcdRtcVector|8 - - # PMEM (NVDIMM) - gMsvmPkgTokenSpaceGuid.PcdPmemRegisterBase|0xEFFE9000 - gMsvmPkgTokenSpaceGuid.PcdPmemEventVector|37 # SPI - - # Networking - gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections|TRUE - - # Processor Aggregator - gMsvmPkgTokenSpaceGuid.PcdProcIdleBase|0xEFFE8000 - gMsvmPkgTokenSpaceGuid.PcdProcIdleEventVector|38 # SPI - - # Networking - gEfiMdePkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|FALSE #Opt out of secure RNG until ARM64 has a way of doing TRNG. - - # GTDT for AArch64. Currently these aren't exposed to guests, and 0 is a valid - # value to configure. Linux will attempt to configure them, so assign valid - # interrupt lines. - gMsvmPkgTokenSpaceGuid.PcdNonSecureEL1TimerGSIV|19 - gMsvmPkgTokenSpaceGuid.PcdVirtualEL1TimerGSIV|20 - gMsvmPkgTokenSpaceGuid.PcdNonSecureEL2TimerGSIV|21 - - # - # Static initial memory config - presumes minimum 64MB in VM - # Page table, stack, and heap are hard-coded in host worker process. - # ARM uses 128KB for stack and heap because it uses 4k pages which leads - # to more entries in the translation table. - # - # Firmware: 0x00000000 to 0x00800000 8MB (Pcds from FDF file) - # PageTable: 0x00800000 to 0x00804000 4KB (starts on 2MB boundary) - # Stack and Heap: 0x00804000 to 0x00824000 128KB - # System Memory (PEI): 0x00824000 to 0x04000000 ~55MB - # - gMsvmPkgTokenSpaceGuid.PcdSystemMemoryBaseAddress|0x00824000 - gMsvmPkgTokenSpaceGuid.PcdSystemMemorySize|0x037EC000 - - # - # The runtime state of this PCD can be modified in the debugger by - # modifying EfiBdDebugPrintGlobalMask and EfiBdDebugPrintComponentMask. - # - # We now expect the host bios device to parse the in-memory advanced logger - # buffer to our tracing facilities - # - # NOTE: Additional debug levels may cause the in-memory advanced logger - # buffer to exceed its defined limit (see PcdAdvancedLoggerPages) - # - gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x804FEF4B - -# Disable asserts when not building debug -!if $(TARGET) == DEBUG - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x47 -!else - gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x06 -!endif - - # - # See REPORT_STATUS_CODE_PROPERTY_nnnnn in ReportStatusCodeLib.h - # - gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x00000007 - - # Prevent reboots due to some memory variables being out of sync, seems - # to only be relevant when supporting S4 (hibernate) - # FUTURE: figure out what this is all about - gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE - - # Support SMBIOS 3.1 - gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0301 - - # Default OEM ID for ACPI table creation, its length must be 0x6 bytes to follow ACPI specification. - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId|"VRTUAL" - - # Default OEM Table ID for ACPI table creation, "MICROSFT", as a SIGNATURE_64 value. - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId|0x5446534F5243494D - - # Default OEM Revision for ACPI table creation. - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision|0x00000001 - - # Default Creator ID for ACPI table creation, "MSFT", as a SIGNATURE_32 value. - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId|0x5446534D - - # Default Creator Revision for ACPI table creation. - gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision|0x00000001 - - # COM port used for feature debugger - gMsvmPkgTokenSpaceGuid.PcdFeatureDebuggerPortUartBase|0xEFFEC000 #COM1 - - # COM port used for advanced logger output - gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0xEFFEB000 #COM2 - - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8 - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1 - gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1 - - # Default setting for serial console terminal type is UTF8 - gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|3 - - # Override defaults to indicate only US english support - gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes|"engeng" - gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes|"en;en-US" - - # Base addresses of memory mapped devices in MMIO space. - gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0xFED40000 - - # Disable TPM platform hierarchy by default - gEfiSecurityPkgTokenSpaceGuid.PcdRandomizePlatformHierarchy|FALSE - - # Disable front page auto power off - gMsGraphicsPkgTokenSpaceGuid.PcdPowerOffDelay|0xffffffff - - # Change PcdBootManagerMenuFile to point to the FrontPage application - gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x8A, 0x70, 0x42, 0x40, 0x2D, 0x0F, 0x23, 0x48, 0xAC, 0x60, 0x0D, 0x77, 0xB3, 0x11, 0x18, 0x89 } - - gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerInBootOrder|FALSE - -[PcdsFeatureFlag.common] - gEfiMdeModulePkgTokenSpaceGuid.PcdInternalEventServicesEnabled|TRUE - - gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerFixedInRAM|FALSE - gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedFileLoggerForceEnable|TRUE - -[PcdsDynamicDefault] - # GIC related config (legacy Hyper-V values as default) - gArmTokenSpaceGuid.PcdGicDistributorBase|0xFFFF0000 # aka GICD - gArmTokenSpaceGuid.PcdGicRedistributorsBase|0xEFFEE000 # aka GICR - - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE - gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE - gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformRecoverySupport|FALSE - - gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0x0 - - gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|4 # 04 = UUID-Based DHCPv6 Unique Identifier (DUID-UUID) - - # UEFI Config information from the BiosDevice - # UEFI_CONFIG_STRUCTURE_COUNT - gMsvmPkgTokenSpaceGuid.PcdConfigBlobSize|0x0 - # UEFI_CONFIG_BIOS_INFORMATION - gMsvmPkgTokenSpaceGuid.PcdLegacyMemoryMap|0x0 - - # UEFI_CONFIG_MADT - gMsvmPkgTokenSpaceGuid.PcdMadtPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdMadtSize|0x0 - - # UEFI_CONFIG_SRAT - gMsvmPkgTokenSpaceGuid.PcdSratPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSratSize|0x0 - - # UEFI_CONFIG_SLIT - gMsvmPkgTokenSpaceGuid.PcdSlitPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSlitSize|0x0 - - # UEFI_CONFIG_PPTT - gMsvmPkgTokenSpaceGuid.PcdPpttPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdPpttSize|0x0 - - # UEFI_CONFIG_MCFG - gMsvmPkgTokenSpaceGuid.PcdMcfgPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdMcfgSize|0x0 - - # UEFI_CONFIG_SSDT - gMsvmPkgTokenSpaceGuid.PcdSsdtPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSsdtSize|0x0 - - # UEFI_CONFIG_HMAT - gMsvmPkgTokenSpaceGuid.PcdHmatPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdHmatSize|0x0 - - # UEFI_CONFIG_IORT - gMsvmPkgTokenSpaceGuid.PcdIortPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdIortSize|0x0 - - # UEFI_CONFIG_MEMORY_MAP - gMsvmPkgTokenSpaceGuid.PcdMemoryMapPtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdMemoryMapSize|0x0 - - # UEFI_CONFIG_ENTROPY - # Points to the actual entropy array, not the containing config structure - gMsvmPkgTokenSpaceGuid.PcdEntropyPtr|0x0 - - # UEFI_CONFIG_BIOS_GUID - # Points to the actual GUID, not the containing config structure - gMsvmPkgTokenSpaceGuid.PcdBiosGuidPtr|0x0 - - # UEFI_CONFIG_SMBIOS_SYSTEM_MANUFACTURER - # Points to a null terminated string of the specified size - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemManufacturerStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemManufacturerSize|0x0 - - # UEFI_CONFIG_SMBIOS_SYSTEM_PRODUCT_NAME - # Points to a null terminated string of the specified size - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemProductNameStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemProductNameSize|0x0 - - # UEFI_CONFIG_SMBIOS_SYSTEM_VERSION - # Points to a null terminated string of the specified size - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemVersionStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemVersionSize|0x0 - - # UEFI_CONFIG_SMBIOS_SYSTEM_SERIAL_NUMBER - # Points to a null terminated string of the specified size - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSerialNumberStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSerialNumberSize|0x0 - - # UEFI_CONFIG_SMBIOS_SYSTEM_SKU_NUMBER - # Points to a null terminated string of the specified size - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSKUNumberStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSKUNumberSize|0x0 - - # UEFI_CONFIG_SMBIOS_SYSTEM_FAMILY - # Points to a null terminated string of the specified size - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemFamilyStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemFamilySize|0x0 - - # UEFI_CONFIG_SMBIOS_BASE_SERIAL_NUMBER - gMsvmPkgTokenSpaceGuid.PcdSmbiosBaseSerialNumberStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosBaseSerialNumberSize|0x0 - - # UEFI_CONFIG_SMBIOS_CHASSIS_SERIAL_NUMBER - gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisSerialNumberStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisSerialNumberSize|0x0 - - # UEFI_CONFIG_SMBIOS_CHASSIS_ASSET_TAG - gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisAssetTagStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisAssetTagSize|0x0 - - # UEFI_CONFIG_SMBIOS_BIOS_LOCK_STRING - gMsvmPkgTokenSpaceGuid.PcdSmbiosBiosLockStringStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosBiosLockStringSize|0x0 - - # UEFI_CONFIG_SMBIOS_3_1_PROCESSOR_INFORMATION - # Defaults are set to Unknown unless otherwise noted - # Processor Type defaults to Central Processor type (CPU) - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorType|0x3 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorID|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorVoltage|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorExternalClock|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorMaxSpeed|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorCurrentSpeed|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorStatus|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorUpgrade|0x1 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorCharacteristics|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorFamily2|0x2 - - # UEFI_CONFIG_SMBIOS_SOCKET_DESIGNATION - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSocketDesignationStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSocketDesignationSize|0x0 - - # UEFI_CONFIG_SMBIOS_PROCESSOR_MANUFACTURER - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorManufacturerStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorManufacturerSize|0x0 - - # UEFI_CONFIG_SMBIOS_PROCESSOR_VERSION - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorVersionStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorVersionSize|0x0 - - # UEFI_CONFIG_SMBIOS_PROCESSOR_SERIAL_NUMBER - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSerialNumberStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSerialNumberSize|0x0 - - # UEFI_CONFIG_SMBIOS_PROCESSOR_ASSET_TAG - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorAssetTagStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorAssetTagSize|0x0 - - # UEFI_CONFIG_SMBIOS_PROCESSOR_PART_NUMBER - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorPartNumberStr|0x0 - gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorPartNumberSize|0x0 - - # UEFI_CONFIG_FLAGS - gMsvmPkgTokenSpaceGuid.PcdSerialControllersEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdPauseAfterBootFailure|FALSE - gMsvmPkgTokenSpaceGuid.PcdPxeIpV6|FALSE - gMsvmPkgTokenSpaceGuid.PcdDebuggerEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdLoadOempTable|FALSE - gMsvmPkgTokenSpaceGuid.PcdTpmEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdHibernateEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdConsoleMode|0x0 - gMsvmPkgTokenSpaceGuid.PcdMemoryAttributesTableEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdVirtualBatteryEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdSgxMemoryEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdProcIdleEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdCxlMemoryEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdIsVmbfsBoot|FALSE - gMsvmPkgTokenSpaceGuid.PcdDisableFrontpage|FALSE - gMsvmPkgTokenSpaceGuid.PcdMediaPresentEnabledByDefault|FALSE - gMsvmPkgTokenSpaceGuid.PcdEnableIMCWhenIsolated|FALSE - gMsvmPkgTokenSpaceGuid.PcdWatchdogEnabled|FALSE - gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE - gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE - - # UEFI_CONFIG_PROCESSOR_INFORMATION - gMsvmPkgTokenSpaceGuid.PcdProcessorCount|0x0 - gMsvmPkgTokenSpaceGuid.PcdProcessorsPerVirtualSocket|0x0 - gMsvmPkgTokenSpaceGuid.PcdThreadsPerProcessor|0x0 - - # UEFI_CONFIG_MMIO_DESCRIPTION - # Currently only two mmio holes, low gap and high gap but we could - # do more in the future. - gMsvmPkgTokenSpaceGuid.PcdLowMmioGapBasePageNumber|0x0 - gMsvmPkgTokenSpaceGuid.PcdLowMmioGapSizeInPages|0x0 - gMsvmPkgTokenSpaceGuid.PcdHighMmioGapBasePageNumber|0x0 - gMsvmPkgTokenSpaceGuid.PcdHighMmioGapSizeInPages|0x0 - - # UEFI_CONFIG_ACPI_TABLE - gMsvmPkgTokenSpaceGuid.PcdAcpiTablePtr|0x0 - gMsvmPkgTokenSpaceGuid.PcdAcpiTableSize|0x0 - - # PcdTpm2HashMask - # This mask is used to indicate which PCRs are intended to be supported by the *platform* (not UEFI software). - # If a PCR is allocated that isn't in this mask, it will be deallocated by Tcg2Pei. - # If a PCR is supported in this mask, but isn't supported by the TPM, the mask will be updated by Tcg2Pei. - gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask|0x00000007 # HASH_ALG_SHA[384 | 256 | 1] - - # PcdTcg2HashAlgorithmBitmap - # This bitmap is updated at runtime by HashLibBaseCryptoRouter. - # It indicates the UEFI at boot with the current FW support for TPM PCR hashing algorithms. - # For this implementation, we promise no support beyond what is provided by the HashLib instances. - gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap|0x00000000 - - # Default TCG2 stack will try to autodect TPM at startup. - # Fix this to dTPM 2.0 and skip the autodetection. - gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x5a, 0xf2, 0x6b, 0x28, 0xc3, 0xc2, 0x8c, 0x40, 0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17} - - ## This PCD defines minimum length(in bytes) of the system preboot TCG event log area(LAML). - # For PC Client Implementation spec up to and including 1.2 the minimum log size is 64KB. - # Increase to 128KB since Linux is measuring more information causing the 64KB buffer to run out. - # @Prompt Minimum length(in bytes) of the system preboot TCG event log area(LAML). - gEfiSecurityPkgTokenSpaceGuid.PcdTcgLogAreaMinLen|0x20000 - - # UEFI_CONFIG_NVDIMM_COUNT - gMsvmPkgTokenSpaceGuid.PcdNvdimmCount|0x0 - - # Isolation configuration - gMsvmPkgTokenSpaceGuid.PcdIsolationArchitecture|0x0 - gMsvmPkgTokenSpaceGuid.PcdIsolationParavisorPresent|FALSE - gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaBoundary|0x0 - gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaCanonicalizationBitmask|0x0 - - # UEFI_CONFIG_PCIE_BAR_APERTURES - gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesPtr|0 - gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesSize|0 - -################################################################################ -# -# Components Section - list of all Modules include for this Platform. -# -################################################################################ - -!include $(SHARED_CRYPTO_PATH)/Driver/Bin/CryptoDriver.inc.dsc - -[Components] - # - # SEC Phase modules - # - MsvmPkg/Sec/SecMain.inf - - # - # PEI Phase modules - # - ArmPkg/Drivers/CpuPei/CpuPei.inf - MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf - MdeModulePkg/Core/Pei/PeiMain.inf - MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf - MdeModulePkg/Universal/PCD/Pei/Pcd.inf - MsvmPkg/PlatformPei/PlatformPei.inf - MsGraphicsPkg/MsUiTheme/Pei/MsUiThemePpi.inf - SecurityPkg/RandomNumberGenerator/RngPei/RngPei.inf { - - RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf - } - - DebuggerFeaturePkg/DebugConfigPei/DebugConfigPei.inf - - # - # DXE Phase modules - # - ArmPkg/Drivers/CpuDxe/CpuDxe.inf - ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf - FatPkg/EnhancedFatDxe/Fat.inf - - MdeModulePkg/Universal/BdsDxe/BdsDxe.inf - MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf - MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf - UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf - MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf - MdeModulePkg/Core/Dxe/DxeMain.inf { - - NULL|MsCorePkg/Library/DebugPortProtocolInstallLib/DebugPortProtocolInstallLib.inf - ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerVirtCounterLib/ArmGenericTimerVirtCounterLib.inf - DebugTransportLib|MsvmPkg/Library/DebugTransportLibMsvm/DebugTransportLibMsvm.inf - DebugAgentLib|DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.inf - PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf - SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf - TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf - TransportLogControlLib|DebuggerFeaturePkg/Library/TransportLogControlLibNull/TransportLogControlLibNull.inf - } - MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf - MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf - MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf { - - CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf - LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf - } - MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf - MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf - MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf { - - UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf - HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf - - gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|1024 - gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|768 - gEfiMdeModulePkgTokenSpaceGuid.PcdSetGraphicsConsoleModeOnStart|FALSE - } - MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf - MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf - MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf - MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf - MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf - MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf - MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf - MdeModulePkg/Universal/Metronome/Metronome.inf - MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf - MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf - MdeModulePkg/Universal/PCD/Dxe/Pcd.inf - MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf - MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { - - SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf - NULL|MsvmPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf - NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf - } - MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf - MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf - - MsGraphicsPkg/DisplayEngineDxe/DisplayEngineDxe.inf - - # Networking components - - NetworkPkg/ArpDxe/ArpDxe.inf - NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.inf - NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf - NetworkPkg/DnsDxe/DnsDxe.inf - NetworkPkg/DpcDxe/DpcDxe.inf - NetworkPkg/HttpDxe/HttpDxe.inf - NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf - NetworkPkg/Ip4Dxe/Ip4Dxe.inf - NetworkPkg/Ip6Dxe/Ip6Dxe.inf - NetworkPkg/MnpDxe/MnpDxe.inf - NetworkPkg/Mtftp4Dxe/Mtftp4Dxe.inf - NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf - NetworkPkg/TcpDxe/TcpDxe.inf - NetworkPkg/TlsDxe/TlsDxe.inf - NetworkPkg/Udp4Dxe/Udp4Dxe.inf - NetworkPkg/Udp6Dxe/Udp6Dxe.inf - NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf - - MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf - MsvmPkg/AcpiTables/AcpiTables.inf - MsvmPkg/AziHsmDxe/AziHsmDxe.inf - MsvmPkg/EfiHvDxe/EfiHvDxe.inf - MsvmPkg/EmclDxe/EmclDxe.inf - MsvmPkg/EventLogDxe/EventLogDxe.inf - MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf - MsvmPkg/NetvscDxe/NetvscDxe.inf - MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf - MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf - MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf - MsvmPkg/SerialDxe/SerialDxe.inf - MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf - MsvmPkg/StorvscDxe/StorvscDxe.inf - MsvmPkg/SynthKeyDxe/SynthKeyDxe.inf - MsvmPkg/SynicTimerDxe/SynicTimerDxe.inf - MsvmPkg/VariableDxe/VariableDxe.inf - MsvmPkg/VideoDxe/VideoDxe.inf - MsvmPkg/VmbfsDxe/VmbfsDxe.inf - MsvmPkg/VmbusDxe/VmbusDxe.inf - MsvmPkg/VmMeasurementDxe/VmMeasurementDxe.inf - MsvmPkg/VpcivscDxe/VpcivscDxe.inf - MsvmPkg/WatchdogTimerDxe/WatchdogTimerDxe.inf - - # Advanced logger components -!if $(FILE_LOGGER) == 1 - AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.inf -!endif - - SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf { - - RngLib|MsvmPkg/Library/MsvmRngLib/MsvmRngLib.inf - } - - # TPM related components - - SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf - - SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { - - Tpm2DeviceLib|MsvmPkg/Library/Tpm2DeviceLib/Tpm2DeviceLib.inf + +# +# Library instance overrides for SEC and PEI +# +[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM] + ArmMmuLib|UefiCpuPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf + ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf + MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf + PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf + PeiServicesTablePointerLib|ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf + StackCheckLib|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf + +# +# Library instance overrides just for SEC +# +[LibraryClasses.common.SEC] + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + +# +# Library instance overrides for PEI +# +[LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM] + FrameBufferMemDrawLib|MsGraphicsPkg/Library/FrameBufferMemDrawLib/FrameBufferMemDrawLibPei.inf + HvHypercallLib|MsvmPkg/Library/HvHypercallLib/PeiHvHypercallLib.inf + HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf + OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf + ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf + WatchdogTimerLib|MsvmPkg/Library/WatchdogTimerLib/WatchdogTimerLib.inf + ResetSystemLib|MdeModulePkg/Library/PeiResetSystemLib/PeiResetSystemLib.inf + +# +# Library instance overrides just for PEI CORE +# +[LibraryClasses.common.PEI_CORE] + AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/PeiCore/AdvancedLoggerLib.inf + PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf + +# +# Library instance overrides just for PEIMs +# +[LibraryClasses.common.PEIM] + AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/Pei/AdvancedLoggerLib.inf + DebugLib|AdvLoggerPkg/Library/PeiDebugLibAdvancedLogger/PeiDebugLibAdvancedLogger.inf + PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf + ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf + PcdDatabaseLoaderLib|MdeModulePkg/Library/PcdDatabaseLoaderLib/Pei/PcdDatabaseLoaderLibPei.inf # MU_CHANGE + RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf + + MsUiThemeLib|MsGraphicsPkg/Library/MsUiThemeLib/Pei/MsUiThemeLib.inf + + +# +# Library instance overrides for DXE +# +[LibraryClasses.common.DXE_CORE, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION] + BootEventLogLib|MsvmPkg/Library/BootEventLogLib/BootEventLogLib.inf + ConfigLib|MsvmPkg/Library/ConfigLib/ConfigLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf + DxeMemoryProtectionHobLib|MdeModulePkg/Library/MemoryProtectionHobLibNull/DxeMemoryProtectionHobLibNull.inf + DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf + DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf + EventLogLib|MsvmPkg/Library/EventLogLib/EventLogLib.inf + ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf + FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf + FrameBufferMemDrawLib|MsGraphicsPkg/Library/FrameBufferMemDrawLib/FrameBufferMemDrawLibDxe.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf + IpIoLib|NetworkPkg/Library/DxeIpIoLib/DxeIpIoLib.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + MemoryTypeInformationChangeLib|MdeModulePkg/Library/MemoryTypeInformationChangeLibNull/MemoryTypeInformationChangeLibNull.inf + MmioAllocationLib|MsvmPkg/Library/MmioAllocationLib/MmioAllocationLib.inf + NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf + PcdDatabaseLoaderLib|MdeModulePkg/Library/PcdDatabaseLoaderLib/Dxe/PcdDatabaseLoaderLibDxe.inf # MU_CHANGE + PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf + RngLib|MsvmPkg/Library/MsvmRngLib/MsvmRngLib.inf + SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf + UdpIoLib|NetworkPkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + WatchdogTimerLib|MsvmPkg/Library/WatchdogTimerLib/WatchdogTimerLib.inf + PciSegmentLib|MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf + PciSegmentInfoLib|MsvmPkg/Library/PciSegmentInfoLib/PciSegmentInfoLib.inf + IoMmuLib|MdeModulePkg/Library/IoMmuLibNull/IoMmuLibNull.inf + +# +# Library instances overrides for just DXE CORE +# +[LibraryClasses.common.DXE_CORE] + AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/DxeCore/AdvancedLoggerLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf + MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf + HvHypercallLib|MsvmPkg/Library/HvHypercallLib/HvHypercallLib.inf +##MSChange Begin +[LibraryClasses.common.DXE_DRIVER] + ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf + PolicyLib|PolicyServicePkg/Library/DxePolicyLib/DxePolicyLib.inf +##MSChange End + Tcg2PhysicalPresencePromptLib|MsvmPkg/Library/Tcg2PhysicalPresencePromptLibApprove/Tcg2PhysicalPresencePromptLibApprove.inf ## MS_CHANGE + PciHostBridgeLib|MsvmPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf + +# +# Library instance overrides for all DXE Drivers +# +[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.DXE_RUNTIME_DRIVER] + HvHypercallLib|MsvmPkg/Library/HvHypercallLib/HvHypercallLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + +# +# Library instance overrides for DXE Drivers and Applications +# +[LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER, LibraryClasses.common.UEFI_APPLICATION] + AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/Dxe/AdvancedLoggerLib.inf + +# +# Library instance overrides for just DXE Runtime Drivers +# +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + AdvancedLoggerLib|AdvLoggerPkg/Library/AdvancedLoggerLib/Runtime/AdvancedLoggerLib.inf + BiosDeviceLib|MsvmPkg/Library/BiosDeviceLib/BiosDeviceRuntimeLib.inf + # runtime drivers shouldn't use UEFI debugging, especially after ExitBootServices() + DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf + ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf + ResetSystemLib|MdeModulePkg/Library/RuntimeResetSystemLib/RuntimeResetSystemLib.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + +# PERF MODULES START +!if $(PERF_TRACE_ENABLE) == TRUE +[PcdsFixedAtBuild] + # Sets bits 0, 3 to enable measurement but skip binding supports + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask|0x9 + # 16M should be enough to fit all the verbose measurements + gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize|0x1000000 + +[LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM] + PerformanceLib|MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf + +[LibraryClasses.common.UEFI_APPLICATION, LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_DRIVER, LibraryClasses.common.UEFI_DRIVER] + PerformanceLib|MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf + +[LibraryClasses.common.DXE_CORE] + PerformanceLib|MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf + +# [Components.common] +# # FBPT Dump App: +# # Note, this has a dependency on ShellLib, so can only build this if also building the shell +# PerformancePkg/Application/FbptDump/FbptDump.inf +!else +[LibraryClasses.common] + PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf +!endif +# PERF MODULES END + +[PcdsFixedAtBuild.common] + # Advanced Logger Config + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerPreMemPages|1 # Size is 4KB + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerPages|1024 # Size is 4MB +!if $(DEBUGLIB_SERIAL) == 1 + !ifdef DEBUG_NOISY + # This enables verbose output + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerHdwPortDebugPrintErrorLevel|0x804FEF4B + !else + # This default turns on errors and warnings + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerHdwPortDebugPrintErrorLevel|0x80000002 + !endif +!else + # We do not want anything out of serial if the flag is not provided + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerHdwPortDebugPrintErrorLevel|0x0 +!endif + + # Feature Debugger Config + DebuggerFeaturePkgTokenSpaceGuid.PcdInitialBreakpointTimeoutMs|0 +!if $(DEBUGGER_ENABLED) == 1 + DebuggerFeaturePkgTokenSpaceGuid.PcdForceEnableDebugger|TRUE +!endif + + # Synthetic Timer Config + gMsvmPkgTokenSpaceGuid.PcdSynicTimerSintIndex|0x1 + gMsvmPkgTokenSpaceGuid.PcdSynicTimerTimerIndex|0x0 + gMsvmPkgTokenSpaceGuid.PcdSynicTimerVector|17 # use PPI for SINTs + gMsvmPkgTokenSpaceGuid.PcdSynicTimerDefaultPeriod|100000 + + # Vmbus Config + gMsvmPkgTokenSpaceGuid.PcdVmbusSintVector|18 # use PPI for SINTs + gMsvmPkgTokenSpaceGuid.PcdVmbusSintIndex|0x2 + # PPI for Linux. Older public kernels used by WSL2 had 16 and 17 hardcoded, so + # use the next available, 18. + gMsvmPkgTokenSpaceGuid.PcdVmbusVector|18 + + # BIOS Device + gMsvmPkgTokenSpaceGuid.PcdBiosBaseAddress|0xEFFED000 + + # Generation Counter Device + gMsvmPkgTokenSpaceGuid.PcdGenCountEventVector|35 # SPI + + # Battery Device + gMsvmPkgTokenSpaceGuid.PcdBatteryBase|0xEFFEA000 + gMsvmPkgTokenSpaceGuid.PcdBatteryEventVector|36 # SPI + + # UART Devices + gMsvmPkgTokenSpaceGuid.PcdCom1RegisterBase|0xEFFEC000 + gMsvmPkgTokenSpaceGuid.PcdCom1Vector|33 # SPI + gMsvmPkgTokenSpaceGuid.PcdCom2RegisterBase|0xEFFEB000 + gMsvmPkgTokenSpaceGuid.PcdCom2Vector|34 # SPI + + # RTC (clock) + gMsvmPkgTokenSpaceGuid.PcdRtcRegisterBase|0x70 + gMsvmPkgTokenSpaceGuid.PcdRtcVector|8 + + # PMEM (NVDIMM) + gMsvmPkgTokenSpaceGuid.PcdPmemRegisterBase|0xEFFE9000 + gMsvmPkgTokenSpaceGuid.PcdPmemEventVector|37 # SPI + + # Networking + gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections|TRUE + + # Processor Aggregator + gMsvmPkgTokenSpaceGuid.PcdProcIdleBase|0xEFFE8000 + gMsvmPkgTokenSpaceGuid.PcdProcIdleEventVector|38 # SPI + + # Networking + gEfiMdePkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|FALSE #Opt out of secure RNG until ARM64 has a way of doing TRNG. + + # GTDT for AArch64. Currently these aren't exposed to guests, and 0 is a valid + # value to configure. Linux will attempt to configure them, so assign valid + # interrupt lines. + gMsvmPkgTokenSpaceGuid.PcdNonSecureEL1TimerGSIV|19 + gMsvmPkgTokenSpaceGuid.PcdVirtualEL1TimerGSIV|20 + gMsvmPkgTokenSpaceGuid.PcdNonSecureEL2TimerGSIV|21 + + # + # Static initial memory config - presumes minimum 64MB in VM + # Page table, stack, and heap are hard-coded in host worker process. + # ARM uses 128KB for stack and heap because it uses 4k pages which leads + # to more entries in the translation table. + # + # Firmware: 0x00000000 to 0x00800000 8MB (Pcds from FDF file) + # PageTable: 0x00800000 to 0x00804000 4KB (starts on 2MB boundary) + # Stack and Heap: 0x00804000 to 0x00824000 128KB + # System Memory (PEI): 0x00824000 to 0x04000000 ~55MB + # + gMsvmPkgTokenSpaceGuid.PcdSystemMemoryBaseAddress|0x00824000 + gMsvmPkgTokenSpaceGuid.PcdSystemMemorySize|0x037EC000 + + # + # The runtime state of this PCD can be modified in the debugger by + # modifying EfiBdDebugPrintGlobalMask and EfiBdDebugPrintComponentMask. + # + # We now expect the host bios device to parse the in-memory advanced logger + # buffer to our tracing facilities + # + # NOTE: Additional debug levels may cause the in-memory advanced logger + # buffer to exceed its defined limit (see PcdAdvancedLoggerPages) + # + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x804FEF4B + +# Disable asserts when not building debug +!if $(TARGET) == DEBUG + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x47 +!else + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x06 +!endif + + # + # See REPORT_STATUS_CODE_PROPERTY_nnnnn in ReportStatusCodeLib.h + # + gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x00000007 + + # Prevent reboots due to some memory variables being out of sync, seems + # to only be relevant when supporting S4 (hibernate) + # FUTURE: figure out what this is all about + gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE + + # Support SMBIOS 3.1 + gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0301 + + # Default OEM ID for ACPI table creation, its length must be 0x6 bytes to follow ACPI specification. + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId|"VRTUAL" + + # Default OEM Table ID for ACPI table creation, "MICROSFT", as a SIGNATURE_64 value. + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId|0x5446534F5243494D + + # Default OEM Revision for ACPI table creation. + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision|0x00000001 + + # Default Creator ID for ACPI table creation, "MSFT", as a SIGNATURE_32 value. + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId|0x5446534D + + # Default Creator Revision for ACPI table creation. + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision|0x00000001 + + # COM port used for feature debugger + gMsvmPkgTokenSpaceGuid.PcdFeatureDebuggerPortUartBase|0xEFFEC000 #COM1 + + # COM port used for advanced logger output + gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0xEFFEB000 #COM2 + + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|115200 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|8 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|1 + gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|1 + + # Default setting for serial console terminal type is UTF8 + gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|3 + + # Override defaults to indicate only US english support + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes|"engeng" + gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultPlatformLangCodes|"en;en-US" + + # Base addresses of memory mapped devices in MMIO space. + gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress|0xFED40000 + + # Disable TPM platform hierarchy by default + gEfiSecurityPkgTokenSpaceGuid.PcdRandomizePlatformHierarchy|FALSE + + # Disable front page auto power off + gMsGraphicsPkgTokenSpaceGuid.PcdPowerOffDelay|0xffffffff + + # Change PcdBootManagerMenuFile to point to the FrontPage application + gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x8A, 0x70, 0x42, 0x40, 0x2D, 0x0F, 0x23, 0x48, 0xAC, 0x60, 0x0D, 0x77, 0xB3, 0x11, 0x18, 0x89 } + + gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerInBootOrder|FALSE + +[PcdsFeatureFlag.common] + gEfiMdeModulePkgTokenSpaceGuid.PcdInternalEventServicesEnabled|TRUE + + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedLoggerFixedInRAM|FALSE + gAdvLoggerPkgTokenSpaceGuid.PcdAdvancedFileLoggerForceEnable|TRUE + +[PcdsDynamicDefault] + # GIC related config (legacy Hyper-V values as default) + gArmTokenSpaceGuid.PcdGicDistributorBase|0xFFFF0000 # aka GICD + gArmTokenSpaceGuid.PcdGicRedistributorsBase|0xEFFEE000 # aka GICR + + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdPlatformRecoverySupport|FALSE + + gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0x0 + + gEfiNetworkPkgTokenSpaceGuid.PcdDhcp6UidType|4 # 04 = UUID-Based DHCPv6 Unique Identifier (DUID-UUID) + + # UEFI Config information from the BiosDevice + # UEFI_CONFIG_STRUCTURE_COUNT + gMsvmPkgTokenSpaceGuid.PcdConfigBlobSize|0x0 + # UEFI_CONFIG_BIOS_INFORMATION + gMsvmPkgTokenSpaceGuid.PcdLegacyMemoryMap|0x0 + + # UEFI_CONFIG_MADT + gMsvmPkgTokenSpaceGuid.PcdMadtPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdMadtSize|0x0 + + # UEFI_CONFIG_SRAT + gMsvmPkgTokenSpaceGuid.PcdSratPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSratSize|0x0 + + # UEFI_CONFIG_SLIT + gMsvmPkgTokenSpaceGuid.PcdSlitPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSlitSize|0x0 + + # UEFI_CONFIG_PPTT + gMsvmPkgTokenSpaceGuid.PcdPpttPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdPpttSize|0x0 + + # UEFI_CONFIG_MCFG + gMsvmPkgTokenSpaceGuid.PcdMcfgPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdMcfgSize|0x0 + + # UEFI_CONFIG_SSDT + gMsvmPkgTokenSpaceGuid.PcdSsdtPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSsdtSize|0x0 + + # UEFI_CONFIG_HMAT + gMsvmPkgTokenSpaceGuid.PcdHmatPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdHmatSize|0x0 + + # UEFI_CONFIG_IORT + gMsvmPkgTokenSpaceGuid.PcdIortPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdIortSize|0x0 + + # UEFI_CONFIG_MEMORY_MAP + gMsvmPkgTokenSpaceGuid.PcdMemoryMapPtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdMemoryMapSize|0x0 + + # UEFI_CONFIG_ENTROPY + # Points to the actual entropy array, not the containing config structure + gMsvmPkgTokenSpaceGuid.PcdEntropyPtr|0x0 + + # UEFI_CONFIG_BIOS_GUID + # Points to the actual GUID, not the containing config structure + gMsvmPkgTokenSpaceGuid.PcdBiosGuidPtr|0x0 + + # UEFI_CONFIG_SMBIOS_SYSTEM_MANUFACTURER + # Points to a null terminated string of the specified size + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemManufacturerStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemManufacturerSize|0x0 + + # UEFI_CONFIG_SMBIOS_SYSTEM_PRODUCT_NAME + # Points to a null terminated string of the specified size + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemProductNameStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemProductNameSize|0x0 + + # UEFI_CONFIG_SMBIOS_SYSTEM_VERSION + # Points to a null terminated string of the specified size + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemVersionStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemVersionSize|0x0 + + # UEFI_CONFIG_SMBIOS_SYSTEM_SERIAL_NUMBER + # Points to a null terminated string of the specified size + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSerialNumberStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSerialNumberSize|0x0 + + # UEFI_CONFIG_SMBIOS_SYSTEM_SKU_NUMBER + # Points to a null terminated string of the specified size + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSKUNumberStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemSKUNumberSize|0x0 + + # UEFI_CONFIG_SMBIOS_SYSTEM_FAMILY + # Points to a null terminated string of the specified size + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemFamilyStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosSystemFamilySize|0x0 + + # UEFI_CONFIG_SMBIOS_BASE_SERIAL_NUMBER + gMsvmPkgTokenSpaceGuid.PcdSmbiosBaseSerialNumberStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosBaseSerialNumberSize|0x0 + + # UEFI_CONFIG_SMBIOS_CHASSIS_SERIAL_NUMBER + gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisSerialNumberStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisSerialNumberSize|0x0 + + # UEFI_CONFIG_SMBIOS_CHASSIS_ASSET_TAG + gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisAssetTagStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosChassisAssetTagSize|0x0 + + # UEFI_CONFIG_SMBIOS_BIOS_LOCK_STRING + gMsvmPkgTokenSpaceGuid.PcdSmbiosBiosLockStringStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosBiosLockStringSize|0x0 + + # UEFI_CONFIG_SMBIOS_3_1_PROCESSOR_INFORMATION + # Defaults are set to Unknown unless otherwise noted + # Processor Type defaults to Central Processor type (CPU) + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorType|0x3 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorID|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorVoltage|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorExternalClock|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorMaxSpeed|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorCurrentSpeed|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorStatus|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorUpgrade|0x1 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorCharacteristics|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorFamily2|0x2 + + # UEFI_CONFIG_SMBIOS_SOCKET_DESIGNATION + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSocketDesignationStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSocketDesignationSize|0x0 + + # UEFI_CONFIG_SMBIOS_PROCESSOR_MANUFACTURER + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorManufacturerStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorManufacturerSize|0x0 + + # UEFI_CONFIG_SMBIOS_PROCESSOR_VERSION + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorVersionStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorVersionSize|0x0 + + # UEFI_CONFIG_SMBIOS_PROCESSOR_SERIAL_NUMBER + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSerialNumberStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorSerialNumberSize|0x0 + + # UEFI_CONFIG_SMBIOS_PROCESSOR_ASSET_TAG + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorAssetTagStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorAssetTagSize|0x0 + + # UEFI_CONFIG_SMBIOS_PROCESSOR_PART_NUMBER + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorPartNumberStr|0x0 + gMsvmPkgTokenSpaceGuid.PcdSmbiosProcessorPartNumberSize|0x0 + + # UEFI_CONFIG_FLAGS + gMsvmPkgTokenSpaceGuid.PcdSerialControllersEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdPauseAfterBootFailure|FALSE + gMsvmPkgTokenSpaceGuid.PcdPxeIpV6|FALSE + gMsvmPkgTokenSpaceGuid.PcdDebuggerEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdLoadOempTable|FALSE + gMsvmPkgTokenSpaceGuid.PcdTpmEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdHibernateEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdConsoleMode|0x0 + gMsvmPkgTokenSpaceGuid.PcdMemoryAttributesTableEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdVirtualBatteryEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdSgxMemoryEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdProcIdleEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdCxlMemoryEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdIsVmbfsBoot|FALSE + gMsvmPkgTokenSpaceGuid.PcdDisableFrontpage|FALSE + gMsvmPkgTokenSpaceGuid.PcdMediaPresentEnabledByDefault|FALSE + gMsvmPkgTokenSpaceGuid.PcdEnableIMCWhenIsolated|FALSE + gMsvmPkgTokenSpaceGuid.PcdWatchdogEnabled|FALSE + gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE + gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE + + # UEFI_CONFIG_PROCESSOR_INFORMATION + gMsvmPkgTokenSpaceGuid.PcdProcessorCount|0x0 + gMsvmPkgTokenSpaceGuid.PcdProcessorsPerVirtualSocket|0x0 + gMsvmPkgTokenSpaceGuid.PcdThreadsPerProcessor|0x0 + + # UEFI_CONFIG_MMIO_DESCRIPTION + # Currently only two mmio holes, low gap and high gap but we could + # do more in the future. + gMsvmPkgTokenSpaceGuid.PcdLowMmioGapBasePageNumber|0x0 + gMsvmPkgTokenSpaceGuid.PcdLowMmioGapSizeInPages|0x0 + gMsvmPkgTokenSpaceGuid.PcdHighMmioGapBasePageNumber|0x0 + gMsvmPkgTokenSpaceGuid.PcdHighMmioGapSizeInPages|0x0 + + # UEFI_CONFIG_ACPI_TABLE + gMsvmPkgTokenSpaceGuid.PcdAcpiTablePtr|0x0 + gMsvmPkgTokenSpaceGuid.PcdAcpiTableSize|0x0 + + # PcdTpm2HashMask + # This mask is used to indicate which PCRs are intended to be supported by the *platform* (not UEFI software). + # If a PCR is allocated that isn't in this mask, it will be deallocated by Tcg2Pei. + # If a PCR is supported in this mask, but isn't supported by the TPM, the mask will be updated by Tcg2Pei. + gEfiSecurityPkgTokenSpaceGuid.PcdTpm2HashMask|0x00000007 # HASH_ALG_SHA[384 | 256 | 1] + + # PcdTcg2HashAlgorithmBitmap + # This bitmap is updated at runtime by HashLibBaseCryptoRouter. + # It indicates the UEFI at boot with the current FW support for TPM PCR hashing algorithms. + # For this implementation, we promise no support beyond what is provided by the HashLib instances. + gEfiSecurityPkgTokenSpaceGuid.PcdTcg2HashAlgorithmBitmap|0x00000000 + + # Default TCG2 stack will try to autodect TPM at startup. + # Fix this to dTPM 2.0 and skip the autodetection. + gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x5a, 0xf2, 0x6b, 0x28, 0xc3, 0xc2, 0x8c, 0x40, 0xb3, 0xb4, 0x25, 0xe6, 0x75, 0x8b, 0x73, 0x17} + + ## This PCD defines minimum length(in bytes) of the system preboot TCG event log area(LAML). + # For PC Client Implementation spec up to and including 1.2 the minimum log size is 64KB. + # Increase to 128KB since Linux is measuring more information causing the 64KB buffer to run out. + # @Prompt Minimum length(in bytes) of the system preboot TCG event log area(LAML). + gEfiSecurityPkgTokenSpaceGuid.PcdTcgLogAreaMinLen|0x20000 + + # UEFI_CONFIG_NVDIMM_COUNT + gMsvmPkgTokenSpaceGuid.PcdNvdimmCount|0x0 + + # Isolation configuration + gMsvmPkgTokenSpaceGuid.PcdIsolationArchitecture|0x0 + gMsvmPkgTokenSpaceGuid.PcdIsolationParavisorPresent|FALSE + gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaBoundary|0x0 + gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaCanonicalizationBitmask|0x0 + + # UEFI_CONFIG_PCIE_BAR_APERTURES + gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesPtr|0 + gMsvmPkgTokenSpaceGuid.PcdPcieBarAperturesSize|0 + +################################################################################ +# +# Components Section - list of all Modules include for this Platform. +# +################################################################################ + +!include $(SHARED_CRYPTO_PATH)/Driver/Bin/CryptoDriver.inc.dsc + +[Components] + # + # SEC Phase modules + # + MsvmPkg/Sec/SecMain.inf + + # + # PEI Phase modules + # + ArmPkg/Drivers/CpuPei/CpuPei.inf + MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf + MdeModulePkg/Core/Pei/PeiMain.inf + MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf + MdeModulePkg/Universal/PCD/Pei/Pcd.inf + MsvmPkg/PlatformPei/PlatformPei.inf + MsGraphicsPkg/MsUiTheme/Pei/MsUiThemePpi.inf + SecurityPkg/RandomNumberGenerator/RngPei/RngPei.inf { + + RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf + } + + DebuggerFeaturePkg/DebugConfigPei/DebugConfigPei.inf + + # + # DXE Phase modules + # + ArmPkg/Drivers/CpuDxe/CpuDxe.inf + ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf + FatPkg/EnhancedFatDxe/Fat.inf + + MdeModulePkg/Universal/BdsDxe/BdsDxe.inf + MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf + MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf + MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf + UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf + MdeModulePkg/Core/Dxe/DxeMain.inf { + + NULL|MsCorePkg/Library/DebugPortProtocolInstallLib/DebugPortProtocolInstallLib.inf + ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerVirtCounterLib/ArmGenericTimerVirtCounterLib.inf + DebugTransportLib|MsvmPkg/Library/DebugTransportLibMsvm/DebugTransportLibMsvm.inf + DebugAgentLib|DebuggerFeaturePkg/Library/DebugAgent/DebugAgentDxe.inf + PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf + SerialPortLib|ArmPlatformPkg/Library/PL011SerialPortLib/PL011SerialPortLib.inf + TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf + TransportLogControlLib|DebuggerFeaturePkg/Library/TransportLogControlLibNull/TransportLogControlLibNull.inf + } + MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf + MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf + MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf + MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf { + + CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf + LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf + } + MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf + MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf + MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf { + + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|1024 + gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|768 + gEfiMdeModulePkgTokenSpaceGuid.PcdSetGraphicsConsoleModeOnStart|FALSE + } + MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf + MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf + MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf + MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf + MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf + MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf + MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf + MdeModulePkg/Universal/Metronome/Metronome.inf + MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf + MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf + MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + + SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf + NULL|MsvmPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf + } + MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf + + MsGraphicsPkg/DisplayEngineDxe/DisplayEngineDxe.inf + + # Security components + SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf + + # Networking components + + NetworkPkg/ArpDxe/ArpDxe.inf + NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.inf + NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf + NetworkPkg/DnsDxe/DnsDxe.inf + NetworkPkg/DpcDxe/DpcDxe.inf + NetworkPkg/HttpDxe/HttpDxe.inf + NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf + NetworkPkg/Ip4Dxe/Ip4Dxe.inf + NetworkPkg/Ip6Dxe/Ip6Dxe.inf + NetworkPkg/MnpDxe/MnpDxe.inf + NetworkPkg/Mtftp4Dxe/Mtftp4Dxe.inf + NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf + NetworkPkg/TcpDxe/TcpDxe.inf + NetworkPkg/TlsDxe/TlsDxe.inf + NetworkPkg/Udp4Dxe/Udp4Dxe.inf + NetworkPkg/Udp6Dxe/Udp6Dxe.inf + NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf + + MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf + MsvmPkg/AcpiTables/AcpiTables.inf + MsvmPkg/AziHsmDxe/AziHsmDxe.inf + MsvmPkg/EfiHvDxe/EfiHvDxe.inf + MsvmPkg/EmclDxe/EmclDxe.inf + MsvmPkg/EventLogDxe/EventLogDxe.inf + MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + MsvmPkg/NetvscDxe/NetvscDxe.inf + MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf + MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf + MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf + MsvmPkg/SerialDxe/SerialDxe.inf + MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf + MsvmPkg/StorvscDxe/StorvscDxe.inf + MsvmPkg/SynthKeyDxe/SynthKeyDxe.inf + MsvmPkg/SynicTimerDxe/SynicTimerDxe.inf + MsvmPkg/VariableDxe/VariableDxe.inf + MsvmPkg/VideoDxe/VideoDxe.inf + MsvmPkg/VmbfsDxe/VmbfsDxe.inf + MsvmPkg/VmbusDxe/VmbusDxe.inf + MsvmPkg/VmMeasurementDxe/VmMeasurementDxe.inf + MsvmPkg/VpcivscDxe/VpcivscDxe.inf + MsvmPkg/WatchdogTimerDxe/WatchdogTimerDxe.inf + + # Advanced logger components +!if $(FILE_LOGGER) == 1 + AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.inf +!endif + + SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf { + + RngLib|MsvmPkg/Library/MsvmRngLib/MsvmRngLib.inf + } + + # TPM related components + + SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf + + SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf { + + Tpm2DeviceLib|MsvmPkg/Library/Tpm2DeviceLib/Tpm2DeviceLib.inf HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf - NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf - NULL|MsvmPkg/Library/Tcg2PreInitLib/Tcg2PreInitLibDxe.inf - } - - SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { - - Tpm2DeviceLib|MsvmPkg/Library/Tpm2DeviceLib/Tpm2DeviceLib.inf - HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf - NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf - NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf - NULL|MsvmPkg/Library/Tcg2PreInitLib/Tcg2PreInitLibPei.inf - } - - MsvmPkg/MsvmTcg2PlatformDxe/MsvmTcg2PlatformDxe.inf { - - Tpm2DeviceLib|MsvmPkg/Library/Tpm2DeviceLib/Tpm2DeviceLib.inf - TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.inf - NULL|MsvmPkg/Library/Tcg2PreInitLib/Tcg2PreInitLibDxe.inf - } - -!if $(LEGACY_DEBUGGER) == 1 - MsKdDebugPkg2/KdDxe/KdDxe.inf { - - PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf - SerialPortLib|MsvmPkg/Library/KdPL011SerialPortLib/KdPL011SerialPortLib.inf - SourceDebugEnabledLib|MsvmPkg/Library/SourceDebugEnabled/SourceDebugEnabledLib.inf - } -!endif - - # UI Theme Protocol - MsGraphicsPkg/MsUiTheme/Dxe/MsUiThemeProtocol.inf - - # Simple Window Manager (SWM) driver. - MsGraphicsPkg/SimpleWindowManagerDxe/SimpleWindowManagerDxe.inf - - # Rendering Engine (SRE) driver. - MsGraphicsPkg/RenderingEngineDxe/RenderingEngineDxe.inf - - # FrontPage application. - MsvmPkg/FrontPage/FrontPage.inf - - MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf { - - LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf - } - -!if $(PRM_ENABLE) == TRUE - # - # PRM Configuration Driver - # - PrmPkg/PrmConfigDxe/PrmConfigDxe.inf { - - NULL|PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf - NULL|PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf - } - - # - # PRM Module Loader Driver - # - PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf - - # - # PRM SSDT Installation Driver - # - PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf - - # - # PRM Sample Modules - # - PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf - PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf -!endif - + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|MsvmPkg/Library/Tcg2PreInitLib/Tcg2PreInitLibDxe.inf + } + + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf { + + Tpm2DeviceLib|MsvmPkg/Library/Tpm2DeviceLib/Tpm2DeviceLib.inf + HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf + NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf + NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf + NULL|MsvmPkg/Library/Tcg2PreInitLib/Tcg2PreInitLibPei.inf + } + + MsvmPkg/MsvmTcg2PlatformDxe/MsvmTcg2PlatformDxe.inf { + + Tpm2DeviceLib|MsvmPkg/Library/Tpm2DeviceLib/Tpm2DeviceLib.inf + TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLib/PeiDxeTpmPlatformHierarchyLib.inf + NULL|MsvmPkg/Library/Tcg2PreInitLib/Tcg2PreInitLibDxe.inf + } + +!if $(LEGACY_DEBUGGER) == 1 + MsKdDebugPkg2/KdDxe/KdDxe.inf { + + PL011UartClockLib|ArmPlatformPkg/Library/PL011UartClockLib/PL011UartClockLib.inf + SerialPortLib|MsvmPkg/Library/KdPL011SerialPortLib/KdPL011SerialPortLib.inf + SourceDebugEnabledLib|MsvmPkg/Library/SourceDebugEnabled/SourceDebugEnabledLib.inf + } +!endif + + # UI Theme Protocol + MsGraphicsPkg/MsUiTheme/Dxe/MsUiThemeProtocol.inf + + # Simple Window Manager (SWM) driver. + MsGraphicsPkg/SimpleWindowManagerDxe/SimpleWindowManagerDxe.inf + + # Rendering Engine (SRE) driver. + MsGraphicsPkg/RenderingEngineDxe/RenderingEngineDxe.inf + + # FrontPage application. + MsvmPkg/FrontPage/FrontPage.inf + + MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf { + + LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf + } + +!if $(PRM_ENABLE) == TRUE + # + # PRM Configuration Driver + # + PrmPkg/PrmConfigDxe/PrmConfigDxe.inf { + + NULL|PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/Library/DxeAcpiParameterBufferModuleConfigLib/DxeAcpiParameterBufferModuleConfigLib.inf + NULL|PrmPkg/Samples/PrmSampleContextBufferModule/Library/DxeContextBufferModuleConfigLib/DxeContextBufferModuleConfigLib.inf + } + + # + # PRM Module Loader Driver + # + PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf + + # + # PRM SSDT Installation Driver + # + PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf + + # + # PRM Sample Modules + # + PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf + PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf +!endif + # TODO: There should be only one [BuildOptions]. -[BuildOptions] - # Generate PDBs on release builds with full debugging, with linker and CC flags +[BuildOptions] + # Generate PDBs on release builds with full debugging, with linker and CC flags MSFT:*_*_*_DLINK_FLAGS = /DEBUG:FULL /PDBALTPATH:$(MODULE_NAME).pdb *_CLANGPDB_*_DLINK_FLAGS = /DEBUG:FULL /PDBALTPATH:$(MODULE_NAME).pdb - # /d2overrideInterlockedIntrinsArm64- inlines Interlocked sequences. - # TODO: And they are ARMv8.0 that ARMcorp says not to use on newer hardware. + # /d2overrideInterlockedIntrinsArm64- inlines Interlocked sequences. + # TODO: And they are ARMv8.0 that ARMcorp says not to use on newer hardware. MSFT:*_*_*_CC_FLAGS = /Z7 /d2overrideInterlockedIntrinsArm64- *_CLANGPDB_*_CC_FLAGS = -g -gcodeview -gcodeview-ghash -gcodeview-command-line *_GCC_*_ASLDLINK_FLAGS = -z common-page-size=0x1000 *_GCC_*_DLINK_FLAGS = -z common-page-size=0x1000 - - # Set file alignment and (memory) alignment to 4K. - # Memory alignment 4K is required for page protection. - # i.e. So that, text/data/rdata are on different pages, - # so that data/rdata are not executable and text/rdata are not writable. - # This is the main reason sections exist and the main feature of the PE format. - # File==memory for execute in place, or loader perf/simplicity otherwise. - # Memory alignment defaults to 4K, if not otherwise changed by build system. + + # Set file alignment and (memory) alignment to 4K. + # Memory alignment 4K is required for page protection. + # i.e. So that, text/data/rdata are on different pages, + # so that data/rdata are not executable and text/rdata are not writable. + # This is the main reason sections exist and the main feature of the PE format. + # File==memory for execute in place, or loader perf/simplicity otherwise. + # Memory alignment defaults to 4K, if not otherwise changed by build system. MSFT:*_*_*_DLINK_FLAGS = -align:4096 -filealign:4096 *_CLANGPDB_*_DLINK_FLAGS = -align:4096 -filealign:4096 diff --git a/MsvmPkg/MsvmPkgAARCH64.fdf b/MsvmPkg/MsvmPkgAARCH64.fdf index 499ef7d78..bde12c6a7 100644 --- a/MsvmPkg/MsvmPkgAARCH64.fdf +++ b/MsvmPkg/MsvmPkgAARCH64.fdf @@ -1,400 +1,402 @@ -## @file -# Microsoft ARM64 Virtual Machine Firmware Flash Description File -# -# Copyright (C) Microsoft. -# SPDX-License-Identifier: BSD-2-Clause-Patent -# -# This file decribes the layout and contents of the firmware image that -# would normally get burned to flash on a physical machine. In a Hyper-V VM -# this image gets put into VM memory by the host VM worker process. The -# net effect is the same. The code is present in the VM memory space. -# -## - -################################################################################ -# This FD section describes the layout of the firmware image. -# -# FD.MSVM - -# 0x800000 +----------------------------+ -# | | -# | DXE modules | -# | | -# | | -# | DXE Volume | -# 0x200000 +----------------------------+ -# | PEI modules | -# | PEI_Core | -# | SEC | -# | | -# | MAIN Volume | -# 0x1000 +----------------------------+ -# | empty page | -# 0x0 +----------------------------+ -# -[FD.MSVM] -BaseAddress = 0x00000000|gMsvmPkgTokenSpaceGuid.PcdFdBaseAddress +## @file +# Microsoft ARM64 Virtual Machine Firmware Flash Description File +# +# Copyright (C) Microsoft. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# This file decribes the layout and contents of the firmware image that +# would normally get burned to flash on a physical machine. In a Hyper-V VM +# this image gets put into VM memory by the host VM worker process. The +# net effect is the same. The code is present in the VM memory space. +# +## + +################################################################################ +# This FD section describes the layout of the firmware image. +# +# FD.MSVM + +# 0x800000 +----------------------------+ +# | | +# | DXE modules | +# | | +# | | +# | DXE Volume | +# 0x200000 +----------------------------+ +# | PEI modules | +# | PEI_Core | +# | SEC | +# | | +# | MAIN Volume | +# 0x1000 +----------------------------+ +# | empty page | +# 0x0 +----------------------------+ +# +[FD.MSVM] +BaseAddress = 0x00000000|gMsvmPkgTokenSpaceGuid.PcdFdBaseAddress !if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG -Size = 0x00810000|gMsvmPkgTokenSpaceGuid.PcdFdSize +Size = 0x00810000|gMsvmPkgTokenSpaceGuid.PcdFdSize !else Size = 0x00800000|gMsvmPkgTokenSpaceGuid.PcdFdSize !endif - -ErasePolarity = 1 -BlockSize = 0x1000 # This multiplied by NumBlocks should == Size + +ErasePolarity = 1 +BlockSize = 0x1000 # This multiplied by NumBlocks should == Size !if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG -NumBlocks = 0x810 +NumBlocks = 0x810 !else NumBlocks = 0x800 !endif - -# -# UEFI has trouble dealing with FVs that reside at physical address 0x0. -# Therefore this dummy 4K page is put at offset zero. An instruction is -# put at the beginning to jump to the beginning of the first FV so the -# processor can start either at the beginning of the image or at the -# beginning of the first FV. -# -0x00000000|0x00001000 -DATA = { - 0x00, 0x04, 0x00, 0x14 # 'b 0x1000' AArch64 instruction -} - -# MAIN volume (start|size) -0x00001000|0x001FF000 -gMsvmPkgTokenSpaceGuid.PcdFvBaseAddress|gMsvmPkgTokenSpaceGuid.PcdFvSize -FV = MAIN - -# DXE volume that is not force rebased so that the section alignment and -# file alignment do not need to match + +# +# UEFI has trouble dealing with FVs that reside at physical address 0x0. +# Therefore this dummy 4K page is put at offset zero. An instruction is +# put at the beginning to jump to the beginning of the first FV so the +# processor can start either at the beginning of the image or at the +# beginning of the first FV. +# +0x00000000|0x00001000 +DATA = { + 0x00, 0x04, 0x00, 0x14 # 'b 0x1000' AArch64 instruction +} + +# MAIN volume (start|size) +0x00001000|0x001FF000 +gMsvmPkgTokenSpaceGuid.PcdFvBaseAddress|gMsvmPkgTokenSpaceGuid.PcdFvSize +FV = MAIN + +# DXE volume that is not force rebased so that the section alignment and +# file alignment do not need to match !if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG 0x00200000|0x00610000 !else 0x00200000|0x00600000 -!endif -gMsvmPkgTokenSpaceGuid.PcdDxeFvBaseAddress|gMsvmPkgTokenSpaceGuid.PcdDxeFvSize -FV = DXE - -################################################################################ -# -# This FV section describes the MAIN volume contents. It contains SEC and PEI -# modules. This section gets forced rebased by the basetools, as it contains -# some XIP modules. DxeMain is in this FV also so that DxeIpl can find and -# load it. However, the DXE modules are in a separate FV so that they can -# not be force rebased, as they are non-XIP and the DXE_RUNTIME_DRIVERs -# do not meet the requirement for force rebasing (that they have section -# alignment and file alignment equivalent). There is an added benefit here -# that PeiCore does not have to spend time enumerating the DXE drivers to -# determine if it needs to launch them or not. -# -[FV.MAIN] -BlockSize = 0x1000 -FvAlignment = 4K -ERASE_POLARITY = 1 -MEMORY_MAPPED = TRUE -STICKY_WRITE = TRUE -LOCK_CAP = TRUE -LOCK_STATUS = TRUE -WRITE_DISABLED_CAP = TRUE -WRITE_ENABLED_CAP = TRUE -WRITE_STATUS = TRUE -WRITE_LOCK_CAP = TRUE -WRITE_LOCK_STATUS = TRUE -READ_DISABLED_CAP = TRUE -READ_ENABLED_CAP = TRUE -READ_STATUS = TRUE -READ_LOCK_CAP = TRUE -READ_LOCK_STATUS = TRUE - -# -# Dispatch these components first in PEI -# -APRIORI PEI { - INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf -} - -# -# SEC and PEI components -# -INF MsvmPkg/Sec/SecMain.inf -INF ArmPkg/Drivers/CpuPei/CpuPei.inf -INF DebuggerFeaturePkg/DebugConfigPei/DebugConfigPei.inf -INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf -INF MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf -INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf -INF MdeModulePkg/Core/Pei/PeiMain.inf -INF MsGraphicsPkg/MsUiTheme/Pei/MsUiThemePpi.inf -INF MsvmPkg/PlatformPei/PlatformPei.inf -INF SecurityPkg/RandomNumberGenerator/RngPei/RngPei.inf -INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf - -!include $(SHARED_CRYPTO_PATH)/Driver/Bin/CryptoDriver.PEI.inc.fdf - -# -# DXE Components -# -INF MdeModulePkg/Core/Dxe/DxeMain.inf - -[FV.DXE] -BlockSize = 0x1000 -FvAlignment = 4K -FvForceRebase = FALSE -ERASE_POLARITY = 1 -MEMORY_MAPPED = TRUE -STICKY_WRITE = TRUE -LOCK_CAP = TRUE -LOCK_STATUS = TRUE -WRITE_DISABLED_CAP = TRUE -WRITE_ENABLED_CAP = TRUE -WRITE_STATUS = TRUE -WRITE_LOCK_CAP = TRUE -WRITE_LOCK_STATUS = TRUE -READ_DISABLED_CAP = TRUE -READ_ENABLED_CAP = TRUE -READ_STATUS = TRUE -READ_LOCK_CAP = TRUE -READ_LOCK_STATUS = TRUE - -# -# Dispatch these components first in DXE -# -APRIORI DXE { - INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf - INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf - INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf - INF MsvmPkg/EfiHvDxe/EfiHvDxe.inf - INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf - INF MsvmPkg/EventLogDxe/EventLogDxe.inf - INF MsvmPkg/SynicTimerDxe/SynicTimerDxe.inf - INF MsvmPkg/VariableDxe/VariableDxe.inf +!endif +gMsvmPkgTokenSpaceGuid.PcdDxeFvBaseAddress|gMsvmPkgTokenSpaceGuid.PcdDxeFvSize +FV = DXE + +################################################################################ +# +# This FV section describes the MAIN volume contents. It contains SEC and PEI +# modules. This section gets forced rebased by the basetools, as it contains +# some XIP modules. DxeMain is in this FV also so that DxeIpl can find and +# load it. However, the DXE modules are in a separate FV so that they can +# not be force rebased, as they are non-XIP and the DXE_RUNTIME_DRIVERs +# do not meet the requirement for force rebasing (that they have section +# alignment and file alignment equivalent). There is an added benefit here +# that PeiCore does not have to spend time enumerating the DXE drivers to +# determine if it needs to launch them or not. +# +[FV.MAIN] +BlockSize = 0x1000 +FvAlignment = 4K +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +# +# Dispatch these components first in PEI +# +APRIORI PEI { + INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf +} + +# +# SEC and PEI components +# +INF MsvmPkg/Sec/SecMain.inf +INF ArmPkg/Drivers/CpuPei/CpuPei.inf +INF DebuggerFeaturePkg/DebugConfigPei/DebugConfigPei.inf +INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf +INF MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf +INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf +INF MdeModulePkg/Core/Pei/PeiMain.inf +INF MsGraphicsPkg/MsUiTheme/Pei/MsUiThemePpi.inf +INF MsvmPkg/PlatformPei/PlatformPei.inf +INF SecurityPkg/RandomNumberGenerator/RngPei/RngPei.inf +INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf + +!include $(SHARED_CRYPTO_PATH)/Driver/Bin/CryptoDriver.PEI.inc.fdf + +# +# DXE Components +# +INF MdeModulePkg/Core/Dxe/DxeMain.inf + +[FV.DXE] +BlockSize = 0x1000 +FvAlignment = 4K +FvForceRebase = FALSE +ERASE_POLARITY = 1 +MEMORY_MAPPED = TRUE +STICKY_WRITE = TRUE +LOCK_CAP = TRUE +LOCK_STATUS = TRUE +WRITE_DISABLED_CAP = TRUE +WRITE_ENABLED_CAP = TRUE +WRITE_STATUS = TRUE +WRITE_LOCK_CAP = TRUE +WRITE_LOCK_STATUS = TRUE +READ_DISABLED_CAP = TRUE +READ_ENABLED_CAP = TRUE +READ_STATUS = TRUE +READ_LOCK_CAP = TRUE +READ_LOCK_STATUS = TRUE + +# +# Dispatch these components first in DXE +# +APRIORI DXE { + INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf + INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf + INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf + INF MsvmPkg/EfiHvDxe/EfiHvDxe.inf + INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf + INF MsvmPkg/EventLogDxe/EventLogDxe.inf + INF MsvmPkg/SynicTimerDxe/SynicTimerDxe.inf + INF MsvmPkg/VariableDxe/VariableDxe.inf INF MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf - INF MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf -} - -INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf -INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf - -!if $(FILE_LOGGER) == 1 - INF AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.inf -!endif - -INF FatPkg/EnhancedFatDxe/Fat.inf - -INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf -INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf -INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf -INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf -INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf -INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf -INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf -INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf -INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf -INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf -INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf -INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf -INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf -INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf -INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf -INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf -INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf -INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf -INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf -INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf -INF MdeModulePkg/Universal/Metronome/Metronome.inf -INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf -INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf -INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf -INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf -INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf -INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf -INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf - -INF MsGraphicsPkg/DisplayEngineDxe/DisplayEngineDxe.inf - -!include $(SHARED_CRYPTO_PATH)/Driver/Bin/CryptoDriver.DXE.inc.fdf - -INF MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf -INF RuleOverride=ACPITABLE MsvmPkg/AcpiTables/AcpiTables.inf -INF MsvmPkg/AziHsmDxe/AziHsmDxe.inf -INF MsvmPkg/EfiHvDxe/EfiHvDxe.inf -INF MsvmPkg/EmclDxe/EmclDxe.inf -INF MsvmPkg/EventLogDxe/EventLogDxe.inf -INF MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf -INF MsvmPkg/NetvscDxe/NetvscDxe.inf -INF MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf + INF MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf +} + +INF ArmPkg/Drivers/CpuDxe/CpuDxe.inf +INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf + +!if $(FILE_LOGGER) == 1 + INF AdvLoggerPkg/AdvancedFileLogger/AdvancedFileLogger.inf +!endif + +INF FatPkg/EnhancedFatDxe/Fat.inf + +INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf +INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf +INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf +INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf +INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf +INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf +INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf +INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf +INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf +INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf +INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf +INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf +INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf +INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf +INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf +INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf +INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf +INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf +INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf +INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf +INF MdeModulePkg/Universal/Metronome/Metronome.inf +INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf +INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf +INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf +INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf +INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf +INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf +INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf + +INF MsGraphicsPkg/DisplayEngineDxe/DisplayEngineDxe.inf + +!include $(SHARED_CRYPTO_PATH)/Driver/Bin/CryptoDriver.DXE.inc.fdf + +INF MsvmPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +INF RuleOverride=ACPITABLE MsvmPkg/AcpiTables/AcpiTables.inf +INF MsvmPkg/AziHsmDxe/AziHsmDxe.inf +INF MsvmPkg/EfiHvDxe/EfiHvDxe.inf +INF MsvmPkg/EmclDxe/EmclDxe.inf +INF MsvmPkg/EventLogDxe/EventLogDxe.inf +INF MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf +INF MsvmPkg/NetvscDxe/NetvscDxe.inf +INF MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf INF MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf -INF MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf -INF MsvmPkg/SerialDxe/SerialDxe.inf -INF MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf -INF MsvmPkg/StorvscDxe/StorvscDxe.inf -INF MsvmPkg/SynicTimerDxe/SynicTimerDxe.inf -INF MsvmPkg/SynthKeyDxe/SynthKeyDxe.inf -INF MsvmPkg/VariableDxe/VariableDxe.inf -INF MsvmPkg/VideoDxe/VideoDxe.inf -INF MsvmPkg/VmbfsDxe/VmbfsDxe.inf -INF MsvmPkg/VmbusDxe/VmbusDxe.inf -INF MsvmPkg/VmMeasurementDxe/VmMeasurementDxe.inf -INF MsvmPkg/VpcivscDxe/VpcivscDxe.inf -INF MsvmPkg/WatchdogTimerDxe/WatchdogTimerDxe.inf - -!if $(PRM_ENABLE) == TRUE -INF PrmPkg/PrmConfigDxe/PrmConfigDxe.inf -INF PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf -INF PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf -INF PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf -INF PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf -!endif - -INF NetworkPkg/ArpDxe/ArpDxe.inf -INF NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.inf -INF NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf -INF NetworkPkg/DnsDxe/DnsDxe.inf -INF NetworkPkg/DpcDxe/DpcDxe.inf -INF NetworkPkg/HttpDxe/HttpDxe.inf -INF NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf -INF NetworkPkg/Ip4Dxe/Ip4Dxe.inf -INF NetworkPkg/Ip6Dxe/Ip6Dxe.inf -INF NetworkPkg/MnpDxe/MnpDxe.inf -INF NetworkPkg/Mtftp4Dxe/Mtftp4Dxe.inf -INF NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf -INF NetworkPkg/TcpDxe/TcpDxe.inf -INF NetworkPkg/TlsDxe/TlsDxe.inf -INF NetworkPkg/Udp4Dxe/Udp4Dxe.inf -INF NetworkPkg/Udp6Dxe/Udp6Dxe.inf -INF NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf - -INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf -INF SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf -INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf -INF MsvmPkg/MsvmTcg2PlatformDxe/MsvmTcg2PlatformDxe.inf - -# UI Theme Protocol. -INF MsGraphicsPkg/MsUiTheme/Dxe/MsUiThemeProtocol.inf -# Rendering Engine (SRE) driver. -INF MsGraphicsPkg/RenderingEngineDxe/RenderingEngineDxe.inf -# Simple Window Manager (SWM) driver. -INF MsGraphicsPkg/SimpleWindowManagerDxe/SimpleWindowManagerDxe.inf - -# FrontPage application. -INF MsvmPkg/FrontPage/FrontPage.inf - -#INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf - -FILE FREEFORM = PCD(gMsvmPkgTokenSpaceGuid.PcdLogoFile) { - SECTION RAW = MsvmPkg/FrontPage/Resources/BootLogo.bmp - SECTION UI = "Logo" - } - -FILE FREEFORM = PCD(gMsvmPkgTokenSpaceGuid.PcdFrontPageLogoFile) { - SECTION RAW = MsvmPkg/FrontPage/Resources/FrontpageLogo.bmp -} - -FILE FREEFORM = PCD(gMsvmPkgTokenSpaceGuid.PcdBootFailIndicatorFile) { - SECTION RAW = MsvmPkg/FrontPage/Resources/NoBoot.bmp -} - -################################################################################ -# Rules section. -[Rule.Common.SEC] - FILE SEC = $(NAMED_GUID) { - PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING ="$(MODULE_NAME)" Optional - VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.PEI_CORE] - FILE PEI_CORE = $(NAMED_GUID) { - PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING ="$(MODULE_NAME)" Optional - VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.PEIM] - FILE PEIM = $(NAMED_GUID) { - PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.PEIM.BINARY] - FILE PEIM = $(NAMED_GUID) { - PEI_DEPEX PEI_DEPEX Optional |.depex - PE32 PE32 Align = Auto |.efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.DXE_CORE] - FILE DXE_CORE = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.DXE_DRIVER] - FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - RAW ACPI Optional |.acpi - RAW ASL Optional |.aml - } - -[Rule.Common.DXE_DRIVER.BINARY] - FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional |.depex - PE32 PE32 |.efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.DXE_RUNTIME_DRIVER] - FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.UEFI_DRIVER] - FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.UEFI_DRIVER.BINARY] - FILE DRIVER = $(NAMED_GUID) { - DXE_DEPEX DXE_DEPEX Optional |.depex - PE32 PE32 |.efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.UEFI_APPLICATION] - FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.UEFI_APPLICATION.BINARY] - FILE APPLICATION = $(NAMED_GUID) { - PE32 PE32 |.efi - UI STRING="$(MODULE_NAME)" Optional - VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) - } - -[Rule.Common.USER_DEFINED.ACPITABLE] - FILE FREEFORM = $(NAMED_GUID) { - RAW ACPI |.acpi - RAW ASL |.aml - } - -[Rule.Common.USER_DEFINED.CSM] - FILE FREEFORM = $(NAMED_GUID) { - RAW BIN |.bin - } +INF MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf +INF MsvmPkg/SerialDxe/SerialDxe.inf +INF MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf +INF MsvmPkg/StorvscDxe/StorvscDxe.inf +INF MsvmPkg/SynicTimerDxe/SynicTimerDxe.inf +INF MsvmPkg/SynthKeyDxe/SynthKeyDxe.inf +INF MsvmPkg/VariableDxe/VariableDxe.inf +INF MsvmPkg/VideoDxe/VideoDxe.inf +INF MsvmPkg/VmbfsDxe/VmbfsDxe.inf +INF MsvmPkg/VmbusDxe/VmbusDxe.inf +INF MsvmPkg/VmMeasurementDxe/VmMeasurementDxe.inf +INF MsvmPkg/VpcivscDxe/VpcivscDxe.inf +INF MsvmPkg/WatchdogTimerDxe/WatchdogTimerDxe.inf + +!if $(PRM_ENABLE) == TRUE +INF PrmPkg/PrmConfigDxe/PrmConfigDxe.inf +INF PrmPkg/Samples/PrmSampleAcpiParameterBufferModule/PrmSampleAcpiParameterBufferModule.inf +INF PrmPkg/Samples/PrmSampleContextBufferModule/PrmSampleContextBufferModule.inf +INF PrmPkg/PrmLoaderDxe/PrmLoaderDxe.inf +INF PrmPkg/PrmSsdtInstallDxe/PrmSsdtInstallDxe.inf +!endif + +INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf + +INF NetworkPkg/ArpDxe/ArpDxe.inf +INF NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.inf +INF NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf +INF NetworkPkg/DnsDxe/DnsDxe.inf +INF NetworkPkg/DpcDxe/DpcDxe.inf +INF NetworkPkg/HttpDxe/HttpDxe.inf +INF NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf +INF NetworkPkg/Ip4Dxe/Ip4Dxe.inf +INF NetworkPkg/Ip6Dxe/Ip6Dxe.inf +INF NetworkPkg/MnpDxe/MnpDxe.inf +INF NetworkPkg/Mtftp4Dxe/Mtftp4Dxe.inf +INF NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf +INF NetworkPkg/TcpDxe/TcpDxe.inf +INF NetworkPkg/TlsDxe/TlsDxe.inf +INF NetworkPkg/Udp4Dxe/Udp4Dxe.inf +INF NetworkPkg/Udp6Dxe/Udp6Dxe.inf +INF NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf + +INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf +INF SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf +INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +INF MsvmPkg/MsvmTcg2PlatformDxe/MsvmTcg2PlatformDxe.inf + +# UI Theme Protocol. +INF MsGraphicsPkg/MsUiTheme/Dxe/MsUiThemeProtocol.inf +# Rendering Engine (SRE) driver. +INF MsGraphicsPkg/RenderingEngineDxe/RenderingEngineDxe.inf +# Simple Window Manager (SWM) driver. +INF MsGraphicsPkg/SimpleWindowManagerDxe/SimpleWindowManagerDxe.inf + +# FrontPage application. +INF MsvmPkg/FrontPage/FrontPage.inf + +#INF MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf + +FILE FREEFORM = PCD(gMsvmPkgTokenSpaceGuid.PcdLogoFile) { + SECTION RAW = MsvmPkg/FrontPage/Resources/BootLogo.bmp + SECTION UI = "Logo" + } + +FILE FREEFORM = PCD(gMsvmPkgTokenSpaceGuid.PcdFrontPageLogoFile) { + SECTION RAW = MsvmPkg/FrontPage/Resources/FrontpageLogo.bmp +} + +FILE FREEFORM = PCD(gMsvmPkgTokenSpaceGuid.PcdBootFailIndicatorFile) { + SECTION RAW = MsvmPkg/FrontPage/Resources/NoBoot.bmp +} + +################################################################################ +# Rules section. +[Rule.Common.SEC] + FILE SEC = $(NAMED_GUID) { + PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEI_CORE] + FILE PEI_CORE = $(NAMED_GUID) { + PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING ="$(MODULE_NAME)" Optional + VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 Align=4K $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.PEIM.BINARY] + FILE PEIM = $(NAMED_GUID) { + PEI_DEPEX PEI_DEPEX Optional |.depex + PE32 PE32 Align = Auto |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_CORE] + FILE DXE_CORE = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + RAW ACPI Optional |.acpi + RAW ASL Optional |.aml + } + +[Rule.Common.DXE_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.DXE_RUNTIME_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_DRIVER.BINARY] + FILE DRIVER = $(NAMED_GUID) { + DXE_DEPEX DXE_DEPEX Optional |.depex + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.UEFI_APPLICATION.BINARY] + FILE APPLICATION = $(NAMED_GUID) { + PE32 PE32 |.efi + UI STRING="$(MODULE_NAME)" Optional + VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER) + } + +[Rule.Common.USER_DEFINED.ACPITABLE] + FILE FREEFORM = $(NAMED_GUID) { + RAW ACPI |.acpi + RAW ASL |.aml + } + +[Rule.Common.USER_DEFINED.CSM] + FILE FREEFORM = $(NAMED_GUID) { + RAW BIN |.bin + } From 9036946a0c0e73e5e44013ab0a21e9884711d08e Mon Sep 17 00:00:00 2001 From: Maheer Aeron Date: Tue, 12 May 2026 17:46:03 +0000 Subject: [PATCH 2/2] Merged PR 15179578: Refactor NVMe Bounce Buffering Into IommuLib MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds bounce buffering logic to a new IommuLib and uses upstream NVMe driver from MU Adds a generic IOMMU bounce-buffer driver (IoMmuDxe) and removes the per-device bounce-buffer implementation that previously lived inside NvmExpressDxe. VpcivscDxe is wired up to delegate DMA mapping to the new IOMMU protocol when running with bounce buffering active and in an isolated environment. On IoMmuDxe entry point, we pre-allocate a pool of 1024 bounce pages that are made host-visible so that on every Map() operation we can pull from this pool. If not enough memory in the pool, we will lazily grow the pool on the fly similar to the old behavior in NvmExpressDxe in mu_msvm. BlockIoPerfTest results: | Read Size | IoMmu Bounce 1024 pages pre-allocated | IoMmuBounce 32 pages preallocated | IoMmu Bounce no pre-allocation (allocations & hypercalls on every map/unmap | Mainline | |---:|---:|---:|---:|---:| | 4 KB | 99.00 µs | 99.90 µs | 1.30 ms | 208.90 µs | | 8 KB | 97.40 µs | 98.80 µs | 1.26 ms | 223.20 µs | | 16 KB | 1.54 ms | 1.34 ms | 2.40 ms | 1.64 ms | | 32 KB | 1.21 ms | 1.99 ms | 2.33 ms | 1.70 ms | | 64 KB | 1.28 ms | 1.30 ms | 2.90 ms | 1.75 ms | | 1024 KB | 2.83 ms | 6.46 ms | 13.57 ms | 8.20 ms | | 20480 KB | 24.52 ms | 32.74 ms | 265.33 ms | 123.27 ms | ---- Code refactoring to extract NVMe bounce buffering logic into a generic IOMMU driver, enabling reuse across multiple DMA-capable drivers. This PR refactors NVMe-specific bounce buffering into a standalone IoMmuDxe driver that implements EDKII_IOMMU_PROTOCOL, providing generic DMA bounce buffering for Hyper-V isolated VMs. The original NvmExpressDxe implementation is removed and replaced with this reusable IOMMU layer. - `/MsvmPkg/IoMmuDxe/IoMmuDxe.c` (new): Implements EDKII_IOMMU_PROTOCOL with `Map`/`Unmap`/`AllocateBuffer`/`FreeBuffer` operations for bounce buffering in isolated VMs - `/MsvmPkg/NvmExpressDxe/`: Entire NvmExpressDxe driver deleted, including `NvmExpressBounce.c`, `NvmExpressHci.c`, `NvmExpressBlockIo.c`, `NvmExpressPassthru.c`, and related files - `IoMmuDxe.c`: Pre-allocates bounce blocks to avoid hypercalls during common Map operations and installs protocol for all VMs (pass-through for non-isolated) Related work items: #52056047, #61261857 --- MsvmPkg/IoMmuDxe/IoMmuBounce.c | 448 ++++ MsvmPkg/IoMmuDxe/IoMmuBounce.h | 205 ++ MsvmPkg/IoMmuDxe/IoMmuDxe.c | 654 ++++++ MsvmPkg/IoMmuDxe/IoMmuDxe.inf | 49 + MsvmPkg/MsvmPkg.dec | 1 - MsvmPkg/MsvmPkgAARCH64.dsc | 5 +- MsvmPkg/MsvmPkgAARCH64.fdf | 3 +- MsvmPkg/MsvmPkgX64.dsc | 33 +- MsvmPkg/MsvmPkgX64.fdf | 57 +- MsvmPkg/NvmExpressDxe/ComponentName.c | 228 -- MsvmPkg/NvmExpressDxe/NvmExpress.c | 1817 ---------------- MsvmPkg/NvmExpressDxe/NvmExpress.h | 874 -------- MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.c | 1889 ----------------- MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.h | 415 ---- MsvmPkg/NvmExpressDxe/NvmExpressBounce.c | 623 ------ MsvmPkg/NvmExpressDxe/NvmExpressBounce.h | 205 -- MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.c | 153 -- MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.h | 121 -- MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf | 101 - MsvmPkg/NvmExpressDxe/NvmExpressDxe.uni | 17 - MsvmPkg/NvmExpressDxe/NvmExpressDxeExtra.uni | 14 - MsvmPkg/NvmExpressDxe/NvmExpressHci.c | 1815 ---------------- MsvmPkg/NvmExpressDxe/NvmExpressHci.h | 107 - .../NvmExpressDxe/NvmExpressMediaSanitize.c | 584 ----- .../NvmExpressDxe/NvmExpressMediaSanitize.h | 191 -- MsvmPkg/NvmExpressDxe/NvmExpressPassthru.c | 1470 ------------- .../UnitTest/MediaSanitizeUnitTest.c | 983 --------- .../UnitTest/MediaSanitizeUnitTestHost.inf | 37 - MsvmPkg/VpcivscDxe/VpcivscDxe.inf | 2 + MsvmPkg/VpcivscDxe/VpcivscPciIo.c | 98 +- 30 files changed, 1478 insertions(+), 11721 deletions(-) create mode 100644 MsvmPkg/IoMmuDxe/IoMmuBounce.c create mode 100644 MsvmPkg/IoMmuDxe/IoMmuBounce.h create mode 100644 MsvmPkg/IoMmuDxe/IoMmuDxe.c create mode 100644 MsvmPkg/IoMmuDxe/IoMmuDxe.inf delete mode 100644 MsvmPkg/NvmExpressDxe/ComponentName.c delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpress.c delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpress.h delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.c delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.h delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressBounce.c delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressBounce.h delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.c delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.h delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressDxe.uni delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressDxeExtra.uni delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressHci.c delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressHci.h delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.c delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.h delete mode 100644 MsvmPkg/NvmExpressDxe/NvmExpressPassthru.c delete mode 100644 MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c delete mode 100644 MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf diff --git a/MsvmPkg/IoMmuDxe/IoMmuBounce.c b/MsvmPkg/IoMmuDxe/IoMmuBounce.c new file mode 100644 index 000000000..914d97500 --- /dev/null +++ b/MsvmPkg/IoMmuDxe/IoMmuBounce.c @@ -0,0 +1,448 @@ +/** @file + Bounce buffer implementation for the Hyper-V IOMMU driver. + + Provides host-visible bounce buffer management for DMA operations in + isolated Hyper-V virtual machines. Adapted from the NvmExpressBounce + implementation to be generic and usable by any DMA-capable driver. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "IoMmuBounce.h" + +#include +#include + +// +// Module globals for host visibility and shared GPA translation. +// +EFI_HV_IVM_PROTOCOL *mHvIvm; +EFI_PHYSICAL_ADDRESS mSharedGpaBoundary; +UINT64 mCanonicalizationMask; + +// +// Allocation tracking. +// +LIST_ENTRY mAllocContextListHead; + +// +// Pre-allocated bounce block pool. Each block is a contiguous host-visible +// region; Map() sub-allocates contiguous page runs from a block via the +// per-block AllocBitmap. +// +LIST_ENTRY mBounceBlockListHead; + + +/** + Initialize the bounce buffer subsystem. Caches PCDs and locates + the hypervisor IVM protocol. + + @retval EFI_SUCCESS Initialization successful. + @retval other Failed to locate the HV IVM protocol. +**/ +EFI_STATUS +IoMmuInitializeBounce ( + VOID + ) +{ + InitializeListHead (&mAllocContextListHead); + InitializeListHead (&mBounceBlockListHead); + + mSharedGpaBoundary = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdIsolationSharedGpaBoundary); + mCanonicalizationMask = PcdGet64 (PcdIsolationSharedGpaCanonicalizationBitmask); + + if (!IsIsolated ()) { + // + // Bounce buffering and host-visibility hypercalls are not used when the + // VM is not isolated, so don't require the HV IVM protocol. + // + mHvIvm = NULL; + return EFI_SUCCESS; + } + + return gBS->LocateProtocol (&gEfiHvIvmProtocolGuid, NULL, (VOID **)&mHvIvm); +} + + +/** + Return TRUE if bounce buffering should be used for DMA operations. + + @retval TRUE The VM is isolated and bounce buffering is required. + @retval FALSE No isolation; DMA can access all memory directly. +**/ +BOOLEAN +IoMmuIsBounceActive ( + VOID + ) +{ + return IsIsolated (); +} + + +/** + Given an address (VA or PA), strip canonicalization and return the + shared GPA above the shared GPA boundary. + + @param[in] Address Input address. + + @retval The shared physical address. +**/ +EFI_PHYSICAL_ADDRESS +IoMmuGetSharedPa ( + IN VOID *Address + ) +{ + EFI_PHYSICAL_ADDRESS Addr; + + Addr = (EFI_PHYSICAL_ADDRESS)(UINTN)Address; + Addr &= ~mCanonicalizationMask; + if (Addr < mSharedGpaBoundary) { + Addr += mSharedGpaBoundary; + } + + return Addr; +} + + +/** + Given an address (VA or PA), return a canonicalized pointer to the + shared GPA alias. + + @param[in] Address Input address. + + @retval Canonicalized shared VA pointer. +**/ +VOID * +IoMmuGetSharedVa ( + IN VOID *Address + ) +{ + return (VOID *)(UINTN)(IoMmuGetSharedPa (Address) | mCanonicalizationMask); +} + + +/** + Make an address range host-visible for DMA. + + @param[in] BaseAddress Base address of the range. + @param[in] PageCount Number of pages in the range. + @param[out] VisibilityContext Context for revoking visibility later. + + @retval EFI_SUCCESS Range is now host-visible. + @retval other Hypervisor call failed. +**/ +EFI_STATUS +IoMmuMakeAddressRangeShared ( + IN VOID *BaseAddress, + IN UINT32 PageCount, + OUT IOMMU_HOST_VISIBILITY_CONTEXT *VisibilityContext + ) +{ + EFI_STATUS Status; + + if (!IsIsolated ()) { + // + // No isolation: host already has access to all guest memory, so + // there is no visibility hypercall to make. Clear the protection + // handle so a later IoMmuMakeAddressRangePrivate is a no-op too. + // + if (VisibilityContext != NULL) { + VisibilityContext->RangeProtectionHandle = NULL; + } + return EFI_SUCCESS; + } + + Status = mHvIvm->MakeAddressRangeHostVisible ( + mHvIvm, + HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE, + BaseAddress, + PageCount * EFI_PAGE_SIZE, + FALSE, + &VisibilityContext->RangeProtectionHandle + ); + + return Status; +} + + +/** + Revoke host visibility for an address range. + + @param[in] VisibilityContext Context from a prior MakeAddressRangeShared call. +**/ +VOID +IoMmuMakeAddressRangePrivate ( + IN IOMMU_HOST_VISIBILITY_CONTEXT *VisibilityContext + ) +{ + if (!IsIsolated ()) { + // + // No isolation: nothing was made host-visible, so nothing to revoke. + // + return; + } + + mHvIvm->MakeAddressRangeNotHostVisible (mHvIvm, &VisibilityContext->RangeProtectionHandle); +} + + +// +// --------------------------------------------------------------------------- +// Pre-allocated bounce block pool. +// +// Each IOMMU_BOUNCE_BLOCK is a contiguous, host-visible region of pages +// allocated below 4GB. Map() requests are satisfied by sub-allocating a +// contiguous run of free pages from one of the blocks (via the per-block +// AllocBitmap). If no existing block can satisfy a request, a new block is +// allocated and made host-visible (one hypercall per new block, not per +// Map). Blocks are kept around for the lifetime of the driver to amortize +// the cost of host-visibility hypercalls across many DMA operations. +// --------------------------------------------------------------------------- +// + +/** + Find the lowest contiguous run of `RunLength` clear bits in `Bitmap`, + considering only bits [0, BitmapSize). Returns the starting bit index + via *StartBit on success. +**/ +STATIC +BOOLEAN +FindFreeRun ( + IN UINT64 *Bitmap, + IN UINT32 BitmapSize, + IN UINT32 RunLength, + OUT UINT32 *StartBit + ) +{ + UINT32 i; + UINT32 Run; + + if ((RunLength == 0) || (RunLength > BitmapSize)) { + return FALSE; + } + + Run = 0; + for (i = 0; i < BitmapSize; i++) { + if ((Bitmap[i >> 6] & ((UINT64)1 << (i & 63))) == 0) { + Run++; + if (Run == RunLength) { + *StartBit = i + 1 - RunLength; + return TRUE; + } + } else { + Run = 0; + } + } + + return FALSE; +} + + +/** + Set or clear a contiguous run of `Count` bits starting at `Start` in + `Bitmap`. `Set` selects between OR (TRUE) and AND-NOT (FALSE). +**/ +STATIC +VOID +UpdateBitmapRun ( + IN OUT UINT64 *Bitmap, + IN UINT32 Start, + IN UINT32 Count, + IN BOOLEAN Set + ) +{ + UINT32 i; + UINT32 Bit; + UINT64 Mask; + + for (i = 0; i < Count; i++) { + Bit = Start + i; + Mask = (UINT64)1 << (Bit & 63); + if (Set) { + Bitmap[Bit >> 6] |= Mask; + } else { + Bitmap[Bit >> 6] &= ~Mask; + } + } +} + + +/** + Allocate a new bounce block of `PageCount` pages, make it host-visible, + and insert it at the tail of the bounce block list. + + @param[in] PageCount Number of pages in the new block. + @param[out] BlockOut The newly allocated block on success. + + @retval EFI_SUCCESS Block allocated and registered. + @retval EFI_OUT_OF_RESOURCES Allocation or hypercall failed. +**/ +EFI_STATUS +IoMmuPreAllocateBounceBlock ( + IN UINT32 PageCount, + OUT PIOMMU_BOUNCE_BLOCK *BlockOut + ) +{ + EFI_STATUS Status; + PIOMMU_BOUNCE_BLOCK Block; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINT32 BitmapWordCount; + + ASSERT (PageCount > 0); + + Block = AllocateZeroPool (sizeof (IOMMU_BOUNCE_BLOCK)); + if (Block == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + BitmapWordCount = (PageCount + 63) / 64; + Block->AllocBitmap = AllocateZeroPool ((UINTN)BitmapWordCount * sizeof (UINT64)); + if (Block->AllocBitmap == NULL) { + FreePool (Block); + return EFI_OUT_OF_RESOURCES; + } + + // + // Allocate the block below 4GB so it can satisfy both 32-bit and + // 64-bit DMA Map() requests without further constraints. + // + PhysicalAddress = SIZE_4GB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + PageCount, + &PhysicalAddress + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "IoMmu: AllocateBounceBlock: AllocatePages(%d pages, <4GB) failed: %r\n", + PageCount, Status)); + FreePool (Block->AllocBitmap); + FreePool (Block); + return Status; + } + + Block->Signature = IOMMU_BOUNCE_BLOCK_SIGNATURE; + Block->BlockBase = (VOID *)(UINTN)PhysicalAddress; + Block->BlockPageCount = PageCount; + Block->BitmapWordCount = BitmapWordCount; + Block->InUsePageCount = 0; + Block->IsHostVisible = FALSE; + + Status = IoMmuMakeAddressRangeShared ( + Block->BlockBase, + PageCount, + &Block->VisibilityContext + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "IoMmu: AllocateBounceBlock: MakeAddressRangeShared failed: %r\n", + Status)); + gBS->FreePages (PhysicalAddress, PageCount); + FreePool (Block->AllocBitmap); + FreePool (Block); + return Status; + } + + Block->IsHostVisible = TRUE; + InsertTailList (&mBounceBlockListHead, &Block->Link); + + DEBUG ((DEBUG_INFO, + "IoMmu: AllocateBounceBlock: Block=%p Base=%p Pages=%d\n", + Block, Block->BlockBase, PageCount)); + + *BlockOut = Block; + return EFI_SUCCESS; +} + + +EFI_STATUS +IoMmuAcquireBouncePages ( + IN UINT32 PageCount, + OUT PIOMMU_BOUNCE_BLOCK *Block, + OUT UINT32 *StartPageIndex, + OUT VOID **BounceBase + ) +{ + LIST_ENTRY *Entry; + PIOMMU_BOUNCE_BLOCK Candidate; + UINT32 StartBit; + EFI_STATUS Status; + UINT32 NewBlockPages; + + if (PageCount == 0) { + return EFI_INVALID_PARAMETER; + } + + StartBit = 0; + + // + // Try to satisfy from an existing pooled block. + // + for (Entry = GetFirstNode (&mBounceBlockListHead); + !IsNull (&mBounceBlockListHead, Entry); + Entry = GetNextNode (&mBounceBlockListHead, Entry)) + { + Candidate = BASE_CR (Entry, IOMMU_BOUNCE_BLOCK, Link); + + if (PageCount > Candidate->BlockPageCount) { + continue; + } + + if (FindFreeRun (Candidate->AllocBitmap, Candidate->BlockPageCount, PageCount, &StartBit)) { + UpdateBitmapRun (Candidate->AllocBitmap, StartBit, PageCount, TRUE); + Candidate->InUsePageCount += PageCount; + + *Block = Candidate; + *StartPageIndex = StartBit; + *BounceBase = (VOID *)((UINTN)Candidate->BlockBase + ((UINTN)StartBit * EFI_PAGE_SIZE)); + return EFI_SUCCESS; + } + } + + // + // No existing block can fit. Allocate a new pooled block large enough + // for this request (at least the default block size to leave room for + // future sub-allocations). The new block requires one + // MakeAddressRangeHostVisible hypercall; subsequent same-or-smaller + // requests reuse the block with no hypercall. + // + NewBlockPages = PageCount; + if (NewBlockPages < IOMMU_BOUNCE_GROWTH_BLOCK_PAGES) { + NewBlockPages = IOMMU_BOUNCE_GROWTH_BLOCK_PAGES; + } + + Status = IoMmuPreAllocateBounceBlock (NewBlockPages, &Candidate); + if (EFI_ERROR (Status)) { + return Status; + } + DEBUG ((DEBUG_INFO, + "IoMmuAcquireBouncePages: Allocated new bounce block %p with %d pages to satisfy request for %d pages\n", + Candidate, Candidate->BlockPageCount, PageCount)); + UpdateBitmapRun (Candidate->AllocBitmap, 0, PageCount, TRUE); + Candidate->InUsePageCount = PageCount; + + *Block = Candidate; + *StartPageIndex = 0; + *BounceBase = Candidate->BlockBase; + return EFI_SUCCESS; +} + + +VOID +IoMmuReleaseBouncePages ( + IN PIOMMU_BOUNCE_BLOCK Block, + IN UINT32 StartPageIndex, + IN UINT32 PageCount + ) +{ + ASSERT (Block != NULL); + ASSERT (Block->Signature == IOMMU_BOUNCE_BLOCK_SIGNATURE); + ASSERT (PageCount > 0); + ASSERT (StartPageIndex + PageCount <= Block->BlockPageCount); + + UpdateBitmapRun (Block->AllocBitmap, StartPageIndex, PageCount, FALSE); + Block->InUsePageCount -= PageCount; +} diff --git a/MsvmPkg/IoMmuDxe/IoMmuBounce.h b/MsvmPkg/IoMmuDxe/IoMmuBounce.h new file mode 100644 index 000000000..3ab011285 --- /dev/null +++ b/MsvmPkg/IoMmuDxe/IoMmuBounce.h @@ -0,0 +1,205 @@ +/** @file + Bounce buffer types and declarations for the Hyper-V IOMMU driver. + + This module provides bounce buffering for DMA operations in isolated + Hyper-V virtual machines. Memory that needs to be visible to the host + for DMA must be explicitly shared via the hypervisor. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// +// Context for tracking host visibility of an address range. +// +typedef struct _IOMMU_HOST_VISIBILITY_CONTEXT +{ + EFI_HV_PROTECTION_HANDLE RangeProtectionHandle; +} IOMMU_HOST_VISIBILITY_CONTEXT; + +// +// Page counts for bounce blocks. Each block is allocated as a contiguous, +// host-visible region below 4GB. Map() requests are satisfied by +// sub-allocating contiguous page runs from a block. +// +// IOMMU_BOUNCE_INITIAL_BLOCK_PAGES: size of the single block pre-allocated +// at driver entry. Sized to absorb large boot-time DMA transfers (e.g. +// NVMe namespace reads up to ~2 MB) without a lazy allocation. +// +// IOMMU_BOUNCE_GROWTH_BLOCK_PAGES: minimum size used when the pool is +// exhausted and a new block must be allocated on demand. The new block +// is sized to MAX(request, growth) so small requests don't reserve a +// disproportionately large region. +// +#define IOMMU_BOUNCE_INITIAL_BLOCK_PAGES 1024 +#define IOMMU_BOUNCE_GROWTH_BLOCK_PAGES 32 + +// +// IOMMU_BOUNCE_BLOCK - a contiguous, host-visible region of pages backing +// Map() requests. The block is kept (and stays host-visible) for the +// lifetime of the driver. Per-page in-use state is tracked via a bitmap +// sized to BlockPageCount. +// +#define IOMMU_BOUNCE_BLOCK_SIGNATURE SIGNATURE_32('i','o','m','b') + +typedef struct _IOMMU_BOUNCE_BLOCK +{ + UINT32 Signature; + LIST_ENTRY Link; + VOID *BlockBase; // contiguous host-visible base (private VA) + UINT32 BlockPageCount; + UINT32 BitmapWordCount; // number of UINT64 words in AllocBitmap + UINT64 *AllocBitmap; // 1 bit per page; 1 = in use + UINT32 InUsePageCount; + BOOLEAN IsHostVisible; + IOMMU_HOST_VISIBILITY_CONTEXT VisibilityContext; +} IOMMU_BOUNCE_BLOCK, *PIOMMU_BOUNCE_BLOCK; + +// +// MAP_CONTEXT - tracking structure for an active Map operation. Stored as +// the Mapping handle returned to callers. Records which bounce block and +// starting page index were sub-allocated so Unmap can release them. +// +#define IOMMU_MAP_CONTEXT_SIGNATURE SIGNATURE_32('i','o','m','c') + +typedef struct _IOMMU_MAP_CONTEXT +{ + UINT32 Signature; + EDKII_IOMMU_OPERATION Operation; + VOID *HostAddress; + UINTN NumberOfBytes; + VOID *BounceBase; // private VA of the sub-allocated bounce region + UINT32 BouncePageCount; + PIOMMU_BOUNCE_BLOCK BounceBlock; // owning block + UINT32 BounceStartPage; // starting page index within block +} IOMMU_MAP_CONTEXT, *PIOMMU_MAP_CONTEXT; + +// +// ALLOC_CONTEXT - tracking structure for an active AllocateBuffer allocation. +// Used by FreeBuffer to revoke host visibility. +// +typedef struct _IOMMU_ALLOC_CONTEXT +{ + LIST_ENTRY Link; + VOID *OriginalAddress; + UINTN Pages; + IOMMU_HOST_VISIBILITY_CONTEXT VisibilityContext; +} IOMMU_ALLOC_CONTEXT, *PIOMMU_ALLOC_CONTEXT; + + +// +// Bounce buffer initialization. +// +EFI_STATUS +IoMmuInitializeBounce ( + VOID + ); + +// +// Returns TRUE if bounce buffering is active (isolated VM with IOMMU). +// +BOOLEAN +IoMmuIsBounceActive ( + VOID + ); + +// +// Address translation helpers for shared GPA. +// +EFI_PHYSICAL_ADDRESS +IoMmuGetSharedPa ( + IN VOID *Address + ); + +VOID * +IoMmuGetSharedVa ( + IN VOID *Address + ); + +// +// Host visibility management. +// +EFI_STATUS +IoMmuMakeAddressRangeShared ( + IN VOID *BaseAddress, + IN UINT32 PageCount, + OUT IOMMU_HOST_VISIBILITY_CONTEXT *VisibilityContext + ); + +VOID +IoMmuMakeAddressRangePrivate ( + IN IOMMU_HOST_VISIBILITY_CONTEXT *VisibilityContext + ); + +// +// Bounce block pool - pre-allocated, host-visible contiguous regions used +// to satisfy Map() requests without per-Map hypercalls. +// + +/** + Pre-allocate a bounce block of `PageCount` pages, make it host-visible, + and add it to the pool. Used to populate the pool at driver init so the + common-case Map() path needs no hypercall. + + @param[in] PageCount Number of pages in the new block. + @param[out] BlockOut The newly allocated block on success. + + @retval EFI_SUCCESS Block allocated and registered. + @retval EFI_OUT_OF_RESOURCES Allocation or hypercall failed. +**/ +EFI_STATUS +IoMmuPreAllocateBounceBlock ( + IN UINT32 PageCount, + OUT PIOMMU_BOUNCE_BLOCK *BlockOut + ); + +/** + Acquire a contiguous run of bounce pages from the pool. Allocates a new + bounce block (and makes it host-visible) on demand if no existing block + has a sufficient contiguous free run. + + @param[in] PageCount Number of contiguous pages required. + @param[out] Block Owning bounce block. + @param[out] StartPageIndex Starting page index within the block. + @param[out] BounceBase Private VA of the start of the run. + + @retval EFI_SUCCESS Pages acquired. + @retval EFI_OUT_OF_RESOURCES Could not acquire/allocate pages. +**/ +EFI_STATUS +IoMmuAcquireBouncePages ( + IN UINT32 PageCount, + OUT PIOMMU_BOUNCE_BLOCK *Block, + OUT UINT32 *StartPageIndex, + OUT VOID **BounceBase + ); + +/** + Release a previously acquired contiguous run of bounce pages back to the + pool. The pages remain host-visible (the owning block stays host-visible + for its lifetime). + + @param[in] Block Owning bounce block. + @param[in] StartPageIndex Starting page index within the block. + @param[in] PageCount Number of pages to release. +**/ +VOID +IoMmuReleaseBouncePages ( + IN PIOMMU_BOUNCE_BLOCK Block, + IN UINT32 StartPageIndex, + IN UINT32 PageCount + ); diff --git a/MsvmPkg/IoMmuDxe/IoMmuDxe.c b/MsvmPkg/IoMmuDxe/IoMmuDxe.c new file mode 100644 index 000000000..e5486f857 --- /dev/null +++ b/MsvmPkg/IoMmuDxe/IoMmuDxe.c @@ -0,0 +1,654 @@ +/** @file + Hyper-V IOMMU DXE driver. + + Implements the EDKII_IOMMU_PROTOCOL for Hyper-V isolated virtual machines. + Provides bounce buffering so that DMA operations use host-visible memory. + This driver only installs the protocol when running in an isolated VM; + non-isolated VMs do not need IOMMU-based DMA translation. + + This is a generic implementation: any driver that uses PciIo or IoMmuLib + for DMA (e.g., NvmExpressDxe, StorvscDxe) benefits from this bounce + buffering transparently. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "IoMmuBounce.h" + +#include +#include +#include +#include + +#include + +// +// External globals from IoMmuBounce.c +// +extern LIST_ENTRY mAllocContextListHead; + + +/** + EDKII_IOMMU_PROTOCOL.SetAttribute - Set IOMMU access attributes. + + For Hyper-V isolation, this is a no-op since visibility is managed + explicitly through the bounce buffer mechanism rather than hardware + page tables. + + @param[in] This Protocol instance. + @param[in] DeviceHandle Device requesting access. + @param[in] Mapping Mapping handle from Map(). + @param[in] IoMmuAccess Access flags (READ/WRITE). + + @retval EFI_SUCCESS Always succeeds. +**/ +STATIC +EFI_STATUS +EFIAPI +IoMmuSetAttribute ( + IN EDKII_IOMMU_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN VOID *Mapping, + IN UINT64 IoMmuAccess + ) +{ + return EFI_SUCCESS; +} + + +/** + EDKII_IOMMU_PROTOCOL.Map - Map a host address for DMA. + + For BusMasterCommonBuffer: the memory was already made host-visible by + AllocateBuffer; returns the shared physical address directly. + + For BusMasterRead (host→device): acquires bounce pages, copies data into + them, and returns the bounce physical address. + + For BusMasterWrite (device→host): acquires bounce pages, zeroes them, + and returns the bounce physical address. Data is copied back on Unmap. + + @param[in] This Protocol instance. + @param[in] Operation DMA operation type. + @param[in] HostAddress System memory address to map. + @param[in,out] NumberOfBytes Bytes to map / bytes mapped. + @param[out] DeviceAddress Resulting DMA address for the device. + @param[out] Mapping Opaque handle for Unmap(). + + @retval EFI_SUCCESS Mapping created successfully. + @retval EFI_OUT_OF_RESOURCES Could not allocate bounce pages. +**/ +STATIC +EFI_STATUS +EFIAPI +IoMmuMap ( + IN EDKII_IOMMU_PROTOCOL *This, + IN EDKII_IOMMU_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +{ + if (!IoMmuIsBounceActive ()) { + // + // Non-isolated path. Mirrors RootBridgeIoMap()'s behavior when + // IoMmuIsPresent() == FALSE: a non-64-bit Read/Write whose buffer + // crosses the 4GB boundary is bounced into memory below 4GB so + // 32-bit-only bus masters can address it. Everything else is an + // identity mapping. CommonBuffer cannot be remapped here; the + // memory has to already be addressable, which IoMmuAllocateBuffer + // guarantees by allocating below 4GB whenever DUAL_ADDRESS_CYCLE + // is not requested. + // + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress; + + if ((Operation != EdkiiIoMmuOperationBusMasterCommonBuffer) && + (Operation != EdkiiIoMmuOperationBusMasterCommonBuffer64) && + (Operation != EdkiiIoMmuOperationBusMasterRead64) && + (Operation != EdkiiIoMmuOperationBusMasterWrite64) && + ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) { + + PIOMMU_MAP_CONTEXT MapContext; + EFI_PHYSICAL_ADDRESS MappedAddress; + UINTN Pages; + EFI_STATUS Status; + + Pages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + MappedAddress = SIZE_4GB - 1; + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + Pages, + &MappedAddress + ); + if (EFI_ERROR (Status)) { + *NumberOfBytes = 0; + return Status; + } + + // + // Read = host->device: pre-populate the bounce buffer. + // + if ((Operation == EdkiiIoMmuOperationBusMasterRead) || + (Operation == EdkiiIoMmuOperationBusMasterRead64)) { + CopyMem ( + (VOID *)(UINTN)MappedAddress, + HostAddress, + *NumberOfBytes + ); + } + + MapContext = AllocatePool (sizeof (IOMMU_MAP_CONTEXT)); + if (MapContext == NULL) { + gBS->FreePages (MappedAddress, Pages); + *NumberOfBytes = 0; + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (MapContext, sizeof (*MapContext)); + MapContext->Signature = IOMMU_MAP_CONTEXT_SIGNATURE; + MapContext->Operation = Operation; + MapContext->HostAddress = HostAddress; + MapContext->NumberOfBytes = *NumberOfBytes; + MapContext->BounceBase = (VOID *)(UINTN)MappedAddress; + MapContext->BouncePageCount = (UINT32)Pages; + // + // BounceBlock == NULL discriminates this non-isolated <4GB + // bounce path from the isolated bounce-block sub-allocation + // path in IoMmuUnmap. + // + MapContext->BounceBlock = NULL; + MapContext->BounceStartPage = 0; + + *DeviceAddress = MappedAddress; + *Mapping = MapContext; + return EFI_SUCCESS; + } + + // + // Either the device can DMA above 4GB or the buffer already lives + // below 4GB; identity-map. + // + *DeviceAddress = PhysicalAddress; + *Mapping = NULL; + return EFI_SUCCESS; + } + + // + // For BusMasterCommonBuffer, the memory was already made host-visible + // via AllocateBuffer. Just return the shared PA. + // + if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer || + Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) { + *DeviceAddress = IoMmuGetSharedPa (HostAddress); + *Mapping = NULL; + return EFI_SUCCESS; + } + + // + // For BusMasterRead/Write, sub-allocate a contiguous run of pages from + // the pre-allocated bounce block pool. The owning block has already + // been made host-visible at allocation time, so this avoids the + // per-Map MakeAddressRangeHostVisible hypercall. + // + { + PIOMMU_MAP_CONTEXT MapContext; + UINT32 BouncePageCount; + VOID *BounceBase; + VOID *SharedVa; + EFI_STATUS Status; + PIOMMU_BOUNCE_BLOCK BounceBlock; + UINT32 BounceStartPage; + UINTN RequestedPages; + + RequestedPages = EFI_SIZE_TO_PAGES (*NumberOfBytes); + + // + // Bounce-block bookkeeping (page indices, bitmap offsets, + // BlockPageCount) is UINT32 throughout. Reject any request that + // would not fit in 32 bits (>16 TiB) up front rather than silently + // truncating. EDKII_IOMMU_PROTOCOL.Map has no realistic caller at + // this size, but the explicit check makes the contract clear. + // + if (RequestedPages > MAX_UINT32) { + DEBUG ((DEBUG_ERROR, + "IoMmuMap: Request too large: %lu pages (max %u)\n", + (UINT64)RequestedPages, MAX_UINT32)); + return EFI_OUT_OF_RESOURCES; + } + + BouncePageCount = (UINT32)RequestedPages; + + // + // The bounce block pool always allocates blocks below 4GB, so the + // run returned here is safe for both 32-bit and 64-bit DMA devices. + // Operation-based DmaMemoryTop checks (4GB cap) are therefore + // implicitly satisfied. + // + Status = IoMmuAcquireBouncePages ( + BouncePageCount, + &BounceBlock, + &BounceStartPage, + &BounceBase + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "IoMmuMap: Failed to acquire %d bounce pages: %r\n", + BouncePageCount, Status)); + return EFI_OUT_OF_RESOURCES; + } + + SharedVa = IoMmuGetSharedVa (BounceBase); + + // + // Zero the entire bounce buffer. For BusMasterRead (host->device), + // this prevents leaking guest data in unused page fragments. For + // BusMasterWrite (device->host), this provides a clean buffer that + // the device will write into (data copied back on Unmap). + // + ZeroMem (SharedVa, (UINTN)BouncePageCount * EFI_PAGE_SIZE); + + if (Operation == EdkiiIoMmuOperationBusMasterRead || + Operation == EdkiiIoMmuOperationBusMasterRead64) { + // + // Host->device transfer: copy data into the zeroed bounce buffer. + // + CopyMem (SharedVa, HostAddress, *NumberOfBytes); + } + + // + // Return the host-visible physical address. + // + *DeviceAddress = IoMmuGetSharedPa (BounceBase); + + // + // Allocate mapping context for Unmap. + // + MapContext = AllocateZeroPool (sizeof (IOMMU_MAP_CONTEXT)); + if (MapContext == NULL) { + IoMmuReleaseBouncePages (BounceBlock, BounceStartPage, BouncePageCount); + return EFI_OUT_OF_RESOURCES; + } + + MapContext->Signature = IOMMU_MAP_CONTEXT_SIGNATURE; + MapContext->Operation = Operation; + MapContext->HostAddress = HostAddress; + MapContext->NumberOfBytes = *NumberOfBytes; + MapContext->BounceBase = BounceBase; + MapContext->BouncePageCount = BouncePageCount; + MapContext->BounceBlock = BounceBlock; + MapContext->BounceStartPage = BounceStartPage; + + *Mapping = MapContext; + } + + return EFI_SUCCESS; +} + + +/** + EDKII_IOMMU_PROTOCOL.Unmap - Complete a Map operation and release resources. + + For BusMasterWrite operations, copies data from the bounce buffer back + to the original host address before releasing the bounce pages. + + @param[in] This Protocol instance. + @param[in] Mapping Mapping handle from Map(). + + @retval EFI_SUCCESS Unmap completed. +**/ +STATIC +EFI_STATUS +EFIAPI +IoMmuUnmap ( + IN EDKII_IOMMU_PROTOCOL *This, + IN VOID *Mapping + ) +{ + PIOMMU_MAP_CONTEXT MapContext; + + if (Mapping == NULL) { + // + // NULL mapping: BusMasterCommonBuffer or no-op. Nothing to do. + // + return EFI_SUCCESS; + } + + MapContext = (PIOMMU_MAP_CONTEXT)Mapping; + ASSERT (MapContext->Signature == IOMMU_MAP_CONTEXT_SIGNATURE); + + // + // Non-isolated <4GB bounce path. Mirrors RootBridgeIoUnmap()'s + // no-IOMMU path: for Write (device->host) copy the bounce buffer + // back into the original host buffer, then free the bounce pages + // and the context. + // + if (MapContext->BounceBlock == NULL) { + if ((MapContext->Operation == EdkiiIoMmuOperationBusMasterWrite) || + (MapContext->Operation == EdkiiIoMmuOperationBusMasterWrite64)) { + CopyMem ( + MapContext->HostAddress, + MapContext->BounceBase, + MapContext->NumberOfBytes + ); + } + + gBS->FreePages ( + (EFI_PHYSICAL_ADDRESS)(UINTN)MapContext->BounceBase, + MapContext->BouncePageCount + ); + FreePool (MapContext); + return EFI_SUCCESS; + } + + // + // Isolated bounce-block path. + // + // For BusMasterWrite (device->host), copy data from bounce to host. + // + if (MapContext->Operation == EdkiiIoMmuOperationBusMasterWrite || + MapContext->Operation == EdkiiIoMmuOperationBusMasterWrite64) { + VOID *SharedVa; + + SharedVa = IoMmuGetSharedVa (MapContext->BounceBase); + CopyMem ( + MapContext->HostAddress, + SharedVa, + MapContext->NumberOfBytes + ); + } + + // + // Release the bounce pages back to the pool. The owning bounce block + // remains host-visible for its lifetime, so no per-Unmap hypercall is + // required. + // + if ((MapContext->Operation != EdkiiIoMmuOperationBusMasterCommonBuffer) && + (MapContext->Operation != EdkiiIoMmuOperationBusMasterCommonBuffer64)) + { + IoMmuReleaseBouncePages ( + MapContext->BounceBlock, + MapContext->BounceStartPage, + MapContext->BouncePageCount + ); + FreePool (MapContext); + + } + + return EFI_SUCCESS; +} + + +/** + EDKII_IOMMU_PROTOCOL.AllocateBuffer - Allocate DMA-capable memory. + + Allocates pages and makes them host-visible so the device can DMA to them. + Returns a canonicalized shared VA that maps above the shared GPA boundary. + + When EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE is not set the allocation is + constrained below 4GB and Type is forced to AllocateMaxAddress. When the + attribute is set, the caller-supplied Type is used as-is. + + @param[in] This Protocol instance. + @param[in] Type Allocation type; overridden to AllocateMaxAddress + when dual-address-cycle is not set. + @param[in] MemoryType Memory type (EfiBootServicesData or EfiRuntimeServicesData). + @param[in] Pages Number of pages to allocate. + @param[in,out] HostAddress On output, the shared VA pointer. + @param[in] Attributes Allocation attributes (EDKII_IOMMU_ATTRIBUTE_*). + + @retval EFI_SUCCESS Memory allocated and made host-visible. + @retval EFI_INVALID_PARAMETER This, HostAddress, or Pages is invalid. + @retval EFI_OUT_OF_RESOURCES Allocation or visibility call failed. +**/ +STATIC +EFI_STATUS +EFIAPI +IoMmuAllocateBuffer ( + IN EDKII_IOMMU_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT VOID **HostAddress, + IN UINT64 Attributes + ) +{ + EFI_STATUS Status; + IOMMU_HOST_VISIBILITY_CONTEXT VisibilityContext; + PIOMMU_ALLOC_CONTEXT AllocContext; + EFI_PHYSICAL_ADDRESS PhysicalAddress; + + if ((This == NULL) || (Pages == 0) || (HostAddress == NULL)) { + DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: Invalid parameter\n")); + Status = EFI_INVALID_PARAMETER; + goto End; + } + + PhysicalAddress = MAX_UINTN; + + if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) { + // + // Device cannot address above 4GB; constrain allocation below 4GB. + // + PhysicalAddress = SIZE_4GB - 1; + Type = AllocateMaxAddress; + } + + Status = gBS->AllocatePages ( + Type, + MemoryType, + Pages, + &PhysicalAddress + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: Failed to allocate pages: %r\n", Status)); + goto End; + } + + if (!IoMmuIsBounceActive ()) { + // + // Non-isolated: just return the allocated buffer directly. + // + *HostAddress = (VOID *)(UINTN)PhysicalAddress; + goto End; + } + + // + // Make the allocated range host-visible for DMA. + // + Status = IoMmuMakeAddressRangeShared ( + (VOID *)(UINTN)PhysicalAddress, + (UINT32)Pages, + &VisibilityContext + ); + if (EFI_ERROR (Status)) { + gBS->FreePages (PhysicalAddress, Pages); + goto End; + } + + // + // Track this allocation so FreeBuffer can revoke visibility. + // + AllocContext = AllocateZeroPool (sizeof (IOMMU_ALLOC_CONTEXT)); + if (AllocContext == NULL) { + IoMmuMakeAddressRangePrivate (&VisibilityContext); + gBS->FreePages (PhysicalAddress, Pages); + Status = EFI_OUT_OF_RESOURCES; + goto End; + } + + AllocContext->OriginalAddress = (VOID *)(UINTN)PhysicalAddress; + AllocContext->Pages = Pages; + AllocContext->VisibilityContext = VisibilityContext; + InsertTailList (&mAllocContextListHead, &AllocContext->Link); + + // + // Return the canonicalized shared VA. + // + *HostAddress = IoMmuGetSharedVa ((VOID *)(UINTN)PhysicalAddress); + +End: + ASSERT_EFI_ERROR (Status); + return Status; +} + + +/** + EDKII_IOMMU_PROTOCOL.FreeBuffer - Free DMA-capable memory. + + Revokes host visibility for the allocation and frees the pages. + + @param[in] This Protocol instance. + @param[in] Pages Number of pages to free. + @param[in] HostAddress The shared VA returned by AllocateBuffer. + + @retval EFI_SUCCESS Visibility revoked and pages freed. +**/ +STATIC +EFI_STATUS +EFIAPI +IoMmuFreeBuffer ( + IN EDKII_IOMMU_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +{ + LIST_ENTRY *Entry; + PIOMMU_ALLOC_CONTEXT AllocContext; + + if (!IoMmuIsBounceActive ()) { + return gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages); + } + + // + // Find the tracking entry and revoke host visibility. + // + for (Entry = GetFirstNode (&mAllocContextListHead); + !IsNull (&mAllocContextListHead, Entry); + Entry = GetNextNode (&mAllocContextListHead, Entry)) { + + AllocContext = BASE_CR (Entry, IOMMU_ALLOC_CONTEXT, Link); + + if (IoMmuGetSharedVa (AllocContext->OriginalAddress) == HostAddress) { + RemoveEntryList (Entry); + IoMmuMakeAddressRangePrivate (&AllocContext->VisibilityContext); + FreePool (AllocContext); + break; + } + } + + gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages); + + return EFI_SUCCESS; +} + + +// +// Protocol instance. +// +STATIC EDKII_IOMMU_PROTOCOL mIoMmuProtocol = { + EDKII_IOMMU_PROTOCOL_REVISION, + IoMmuSetAttribute, + IoMmuMap, + IoMmuUnmap, + IoMmuAllocateBuffer, + IoMmuFreeBuffer +}; + + +/** + IoMmuDxe driver entry point. + + Initializes the bounce buffer subsystem and installs the EDKII_IOMMU_PROTOCOL. + In isolated VMs, the protocol provides bounce buffering for DMA. In non-isolated + VMs, the protocol provides simple pass-through behavior (identity mapping, + standard allocation). The protocol is always installed to satisfy the + IoMmuLib AARCH64 DEPEX requirement. + + @param[in] ImageHandle Handle for this driver image. + @param[in] SystemTable Pointer to the UEFI system table. + + @retval EFI_SUCCESS Protocol installed successfully. + @retval other Initialization failed. +**/ +EFI_STATUS +EFIAPI +IoMmuDxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (IoMmuIsBounceActive ()) { + // + // Bounce buffering is required: initialize the bounce buffer + // subsystem (caches PCDs, locates the HV IVM protocol, initializes + // list heads). + // + Status = IoMmuInitializeBounce (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IoMmuDxe: Failed to initialize bounce buffers: %r\n", Status)); + return Status; + } + + // + // Pre-allocate one bounce block up front so the common-case Map() + // path needs no AllocatePages/MakeAddressRangeHostVisible hypercall. + // Failure here is non-fatal: subsequent Map() calls will lazily + // allocate a block on demand. + // + { + PIOMMU_BOUNCE_BLOCK InitialBlock; + EFI_STATUS BlockStatus; + + BlockStatus = IoMmuPreAllocateBounceBlock ( + IOMMU_BOUNCE_INITIAL_BLOCK_PAGES, + &InitialBlock + ); + if (EFI_ERROR (BlockStatus)) { + DEBUG ((DEBUG_WARN, + "IoMmuDxe: Failed to pre-allocate initial bounce block: %r\n", + BlockStatus)); + } else { + DEBUG ((DEBUG_INFO, + "IoMmuDxe: Pre-allocated initial bounce block (%d pages)\n", + IOMMU_BOUNCE_INITIAL_BLOCK_PAGES)); + } + } + + DEBUG ((DEBUG_INFO, "IoMmuDxe: Bounce buffers initialized\n")); + } else { + // + // Bounce buffering not required: initialize allocation tracking + // list head only. No bounce blocks or HV protocol needed. + // + InitializeListHead (&mAllocContextListHead); + DEBUG ((DEBUG_INFO, "IoMmuDxe: Bounce buffering inactive, installing pass-through IOMMU protocol\n")); + } + + // + // Always install the IOMMU protocol. On AARCH64, the IoMmuLib has a DEPEX + // on this protocol, so it must be available for VpcivscDxe (and any other + // IoMmuLib consumer) to load. + // + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEdkiiIoMmuProtocolGuid, + EFI_NATIVE_INTERFACE, + &mIoMmuProtocol + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "IoMmuDxe: Failed to install IOMMU protocol: %r\n", Status)); + return Status; + } + + DEBUG ((DEBUG_INFO, "IoMmuDxe: IOMMU protocol installed\n")); + + return EFI_SUCCESS; +} diff --git a/MsvmPkg/IoMmuDxe/IoMmuDxe.inf b/MsvmPkg/IoMmuDxe/IoMmuDxe.inf new file mode 100644 index 000000000..5bb3a9de7 --- /dev/null +++ b/MsvmPkg/IoMmuDxe/IoMmuDxe.inf @@ -0,0 +1,49 @@ +## @file +# Hyper-V IOMMU DXE Driver +# +# Implements the EDKII_IOMMU_PROTOCOL for Hyper-V isolated virtual machines. +# Provides generic bounce buffering for DMA operations so that any driver +# using PciIo/IoMmuLib can transparently perform DMA in isolated VMs. +# +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = IoMmuDxe + FILE_GUID = 7E3B4F5A-1C2D-4E8F-9A0B-D6C5E4F3A2B1 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = IoMmuDxeEntryPoint + +[Sources] + IoMmuBounce.c + IoMmuDxe.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + MsvmPkg/MsvmPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + IsolationLib + MemoryAllocationLib + PcdLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEdkiiIoMmuProtocolGuid ## PRODUCES + gEfiHvIvmProtocolGuid ## CONSUMES + +[Pcd] + gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaBoundary + gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaCanonicalizationBitmask + +[Depex] + TRUE diff --git a/MsvmPkg/MsvmPkg.dec b/MsvmPkg/MsvmPkg.dec index c432df5ee..b326956e9 100644 --- a/MsvmPkg/MsvmPkg.dec +++ b/MsvmPkg/MsvmPkg.dec @@ -298,7 +298,6 @@ gMsvmPkgTokenSpaceGuid.PcdHostEmulatorsWhenHardwareIsolated|FALSE|BOOLEAN|0x6064 gMsvmPkgTokenSpaceGuid.PcdTpmLocalityRegsEnabled|FALSE|BOOLEAN|0x6065 gMsvmPkgTokenSpaceGuid.PcdMtrrsInitializedAtLoad|FALSE|BOOLEAN|0x6067 - gMsvmPkgTokenSpaceGuid.PcdNvmeNamespaceFilter|FALSE|BOOLEAN|0x6068 # UEFI_CONFIG_PROCESSOR_INFORMATION gMsvmPkgTokenSpaceGuid.PcdProcessorCount|0x0|UINT32|0x6032 diff --git a/MsvmPkg/MsvmPkgAARCH64.dsc b/MsvmPkg/MsvmPkgAARCH64.dsc index 8c217cbc8..48dccb27c 100644 --- a/MsvmPkg/MsvmPkgAARCH64.dsc +++ b/MsvmPkg/MsvmPkgAARCH64.dsc @@ -262,6 +262,7 @@ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf + IoMmuLib|MdeModulePkg/Library/IoMmuLib/IoMmuLib.inf IpIoLib|NetworkPkg/Library/DxeIpIoLib/DxeIpIoLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf MemoryTypeInformationChangeLib|MdeModulePkg/Library/MemoryTypeInformationChangeLibNull/MemoryTypeInformationChangeLibNull.inf @@ -281,7 +282,6 @@ WatchdogTimerLib|MsvmPkg/Library/WatchdogTimerLib/WatchdogTimerLib.inf PciSegmentLib|MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf PciSegmentInfoLib|MsvmPkg/Library/PciSegmentInfoLib/PciSegmentInfoLib.inf - IoMmuLib|MdeModulePkg/Library/IoMmuLibNull/IoMmuLibNull.inf # # Library instances overrides for just DXE CORE @@ -789,6 +789,7 @@ FatPkg/EnhancedFatDxe/Fat.inf MdeModulePkg/Universal/BdsDxe/BdsDxe.inf + MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf @@ -878,8 +879,8 @@ MsvmPkg/EventLogDxe/EventLogDxe.inf MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf MsvmPkg/NetvscDxe/NetvscDxe.inf - MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf + MsvmPkg/IoMmuDxe/IoMmuDxe.inf MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf MsvmPkg/SerialDxe/SerialDxe.inf MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf diff --git a/MsvmPkg/MsvmPkgAARCH64.fdf b/MsvmPkg/MsvmPkgAARCH64.fdf index bde12c6a7..9a5d459b5 100644 --- a/MsvmPkg/MsvmPkgAARCH64.fdf +++ b/MsvmPkg/MsvmPkgAARCH64.fdf @@ -180,6 +180,7 @@ INF ArmPkg/Drivers/ArmGicDxe/ArmGicDxe.inf INF FatPkg/EnhancedFatDxe/Fat.inf +INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf @@ -221,8 +222,8 @@ INF MsvmPkg/EmclDxe/EmclDxe.inf INF MsvmPkg/EventLogDxe/EventLogDxe.inf INF MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf INF MsvmPkg/NetvscDxe/NetvscDxe.inf -INF MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf INF MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf +INF MsvmPkg/IoMmuDxe/IoMmuDxe.inf INF MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf INF MsvmPkg/SerialDxe/SerialDxe.inf INF MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf diff --git a/MsvmPkg/MsvmPkgX64.dsc b/MsvmPkg/MsvmPkgX64.dsc index d3e8526ea..ff9a24e29 100644 --- a/MsvmPkg/MsvmPkgX64.dsc +++ b/MsvmPkg/MsvmPkgX64.dsc @@ -37,18 +37,18 @@ ################################################################################ [BuildOptions] *_*_*_GENFW_FLAGS = --keepexceptiontable - *_*_*_CC_FLAGS = -D MS_HYP_CHANGE_BEGIN -D MS_HYP_CHANGE -D MS_HYP -D MU_CHANGE - DEBUG_*_*_CC_FLAGS = -D DEBUG_PLATFORM + *_*_*_CC_FLAGS = -D MS_HYP_CHANGE_BEGIN -D MS_HYP_CHANGE -D MS_HYP -D MU_CHANGE + DEBUG_*_*_CC_FLAGS = -D DEBUG_PLATFORM # Generate PDBs on release builds with full debugging, with linker and CC flags MSFT:*_*_*_DLINK_FLAGS = /DEBUG:FULL /PDBALTPATH:$(MODULE_NAME).pdb - *_CLANGPDB_*_DLINK_FLAGS = /DEBUG:FULL /PDBALTPATH:$(MODULE_NAME).pdb + *_CLANGPDB_*_DLINK_FLAGS = /DEBUG:FULL /PDBALTPATH:$(MODULE_NAME).pdb MSFT:*_*_*_CC_FLAGS = /Z7 - *_CLANGPDB_*_CC_FLAGS = -g -gcodeview -gcodeview-ghash -gcodeview-command-line - - *_GCC_*_ASLDLINK_FLAGS = -z common-page-size=0x1000 - *_GCC_*_DLINK_FLAGS = -z common-page-size=0x1000 - *_CLANGPDB_X64_DLINK_FLAGS = -align:4096 + *_CLANGPDB_*_CC_FLAGS = -g -gcodeview -gcodeview-ghash -gcodeview-command-line + + *_GCC_*_ASLDLINK_FLAGS = -z common-page-size=0x1000 + *_GCC_*_DLINK_FLAGS = -z common-page-size=0x1000 + *_CLANGPDB_X64_DLINK_FLAGS = -align:4096 # Set file alignment and (memory) alignment to 4K. # Memory alignment 4K is required for page protection. @@ -59,12 +59,12 @@ # The linker defaults to -align:4096, but this could be preceded by a lower -align specified # elsewhere in EFI build system. [BuildOptions.common.EDKII.DXE_CORE] - MSFT:*_*_*_DLINK_FLAGS = -align:4096 -filealign:4096 - *_CLANGPDB_*_DLINK_FLAGS = -align:4096 -filealign:4096 + MSFT:*_*_*_DLINK_FLAGS = -align:4096 -filealign:4096 + *_CLANGPDB_*_DLINK_FLAGS = -align:4096 -filealign:4096 [BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.PEIM, BuildOptions.common.EDKII.PEI_CORE] - MSFT:*_*_*_DLINK_FLAGS = -align:4096 -filealign:4096 - *_CLANGPDB_*_DLINK_FLAGS = -align:4096 -filealign:4096 + MSFT:*_*_*_DLINK_FLAGS = -align:4096 -filealign:4096 + *_CLANGPDB_*_DLINK_FLAGS = -align:4096 -filealign:4096 ################################################################################ # @@ -258,6 +258,7 @@ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf + IoMmuLib|MdeModulePkg/Library/IoMmuLib/IoMmuLib.inf IpIoLib|NetworkPkg/Library/DxeIpIoLib/DxeIpIoLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf DxeMemoryProtectionHobLib|MdeModulePkg/Library/MemoryProtectionHobLibNull/DxeMemoryProtectionHobLibNull.inf @@ -278,7 +279,6 @@ WatchdogTimerLib|MsvmPkg/Library/WatchdogTimerLib/WatchdogTimerLib.inf PciSegmentLib|MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf PciSegmentInfoLib|MsvmPkg/Library/PciSegmentInfoLib/PciSegmentInfoLib.inf - IoMmuLib|MdeModulePkg/Library/IoMmuLibNull/IoMmuLibNull.inf # # Library instances overrides for just DXE CORE @@ -876,6 +876,7 @@ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf + MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf @@ -916,8 +917,8 @@ MsvmPkg/AziHsmDxe/AziHsmDxe.inf MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf MsvmPkg/NetvscDxe/NetvscDxe.inf - MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf + MsvmPkg/IoMmuDxe/IoMmuDxe.inf MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf MsvmPkg/StorvscDxe/StorvscDxe.inf @@ -964,8 +965,8 @@ NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf NULL|MsvmPkg/Library/Tcg2PreInitLib/Tcg2PreInitLibPei.inf - #special library For HyperV so that boot doesn't measure FVs - NULL|MsvmPkg/Library/ExcludeFvsFromMeasurementLib/ExcludeFvsFromMeasurementLib.inf + #special library For HyperV so that boot doesn't measure FVs + NULL|MsvmPkg/Library/ExcludeFvsFromMeasurementLib/ExcludeFvsFromMeasurementLib.inf } MsvmPkg/MsvmTcg2PlatformDxe/MsvmTcg2PlatformDxe.inf { diff --git a/MsvmPkg/MsvmPkgX64.fdf b/MsvmPkg/MsvmPkgX64.fdf index fe965e652..00ff3c96b 100644 --- a/MsvmPkg/MsvmPkgX64.fdf +++ b/MsvmPkg/MsvmPkgX64.fdf @@ -46,45 +46,45 @@ # [FD.MSVM] -BaseAddress = 0x00100000|gMsvmPkgTokenSpaceGuid.PcdFdBaseAddress -!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG -Size = 0x00800000|gMsvmPkgTokenSpaceGuid.PcdFdSize -!else -Size = 0x00600000|gMsvmPkgTokenSpaceGuid.PcdFdSize -!endif +BaseAddress = 0x00100000|gMsvmPkgTokenSpaceGuid.PcdFdBaseAddress +!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG +Size = 0x00800000|gMsvmPkgTokenSpaceGuid.PcdFdSize +!else +Size = 0x00600000|gMsvmPkgTokenSpaceGuid.PcdFdSize +!endif ErasePolarity = 1 BlockSize = 0x1000 -!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG -NumBlocks = 0x800 -!else -NumBlocks = 0x600 -!endif +!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG +NumBlocks = 0x800 +!else +NumBlocks = 0x600 +!endif # DXE volume that is not force rebased so that the section alignment and # file alignment do not need to match -!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG -0x00000000|0x00500000 -!else -0x00000000|0x004E0000 -!endif +!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG +0x00000000|0x00500000 +!else +0x00000000|0x004E0000 +!endif gMsvmPkgTokenSpaceGuid.PcdDxeFvBaseAddress|gMsvmPkgTokenSpaceGuid.PcdDxeFvSize FV = DXE # The MAIN volume (start|size) -!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG -0x00500000|0x100000 -!else -0x004E0000|0x100000 +!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG +0x00500000|0x100000 +!else +0x004E0000|0x100000 !endif gMsvmPkgTokenSpaceGuid.PcdFvBaseAddress|gMsvmPkgTokenSpaceGuid.PcdFvSize FV = MAINFV # The SEC volume (start|size) -!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG -0x00600000|0x00020000 -!else -0x005E0000|0x00020000 +!if $(TOOL_CHAIN_TAG) == GCC and $(TARGET) == DEBUG +0x00600000|0x00020000 +!else +0x005E0000|0x00020000 !endif FV = SECFV @@ -93,7 +93,7 @@ FV = SECFV # This FV section describes the SEC volume contents. # [FV.SECFV] -BlockSize = 0x1000 +BlockSize = 0x1000 FvAlignment = 16 ERASE_POLARITY = 1 MEMORY_MAPPED = TRUE @@ -212,7 +212,7 @@ APRIORI DXE { INF MsvmPkg/EventLogDxe/EventLogDxe.inf INF MsvmPkg/SynicTimerDxe/SynicTimerDxe.inf INF MsvmPkg/VariableDxe/VariableDxe.inf - INF MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf + INF MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf INF MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf } @@ -223,6 +223,7 @@ APRIORI DXE { INF FatPkg/EnhancedFatDxe/Fat.inf +INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf @@ -266,8 +267,8 @@ INF MsvmPkg/EmclDxe/EmclDxe.inf INF MsvmPkg/EventLogDxe/EventLogDxe.inf INF MsvmPkg/MsvmPcAtRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf INF MsvmPkg/NetvscDxe/NetvscDxe.inf -INF MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf -INF MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf +INF MsvmPkg/EfiDiagnosticsDxe/EfiDiagnosticsDxe.inf +INF MsvmPkg/IoMmuDxe/IoMmuDxe.inf INF MsvmPkg/PlatformDeviceStateHelper/PlatformDeviceStateHelper.inf INF MsvmPkg/SerialDxe/SerialDxe.inf INF MsvmPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf diff --git a/MsvmPkg/NvmExpressDxe/ComponentName.c b/MsvmPkg/NvmExpressDxe/ComponentName.c deleted file mode 100644 index a58646b43..000000000 --- a/MsvmPkg/NvmExpressDxe/ComponentName.c +++ /dev/null @@ -1,228 +0,0 @@ -/** @file - NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows - NVM Express specification. - - Copyright (c) 2013, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "NvmExpress.h" - -// -// EFI Component Name Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gNvmExpressComponentName = { - NvmExpressComponentNameGetDriverName, - NvmExpressComponentNameGetControllerName, - "eng" -}; - -// -// EFI Component Name 2 Protocol -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gNvmExpressComponentName2 = { - (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NvmExpressComponentNameGetDriverName, - (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NvmExpressComponentNameGetControllerName, - "en" -}; - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mNvmExpressDriverNameTable[] = { - { "eng;en", L"NVM Express Driver" }, - { NULL, NULL } -}; - -GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mNvmExpressControllerNameTable[] = { - { "eng;en", L"NVM Express Controller" }, - { NULL, NULL } -}; - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -NvmExpressComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ) -{ - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - mNvmExpressDriverNameTable, - DriverName, - (BOOLEAN)(This == &gNvmExpressComponentName) - ); -} - -/** - Retrieves a Unicode string that is the user readable name of the controller - that is being managed by a driver. - - This function retrieves the user readable name of the controller specified by - ControllerHandle and ChildHandle in the form of a Unicode string. If the - driver specified by This has a user readable name in the language specified by - Language, then a pointer to the controller name is returned in ControllerName, - and EFI_SUCCESS is returned. If the driver specified by This is not currently - managing the controller specified by ControllerHandle and ChildHandle, - then EFI_UNSUPPORTED is returned. If the driver specified by This does not - support the language specified by Language, then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param ControllerHandle[in] The handle of a controller that the driver - specified by This is managing. This handle - specifies the controller whose name is to be - returned. - - @param ChildHandle[in] The handle of the child controller to retrieve - the name of. This is an optional parameter that - may be NULL. It will be NULL for device - drivers. It will also be NULL for a bus drivers - that wish to retrieve the name of the bus - controller. It will not be NULL for a bus - driver that wishes to retrieve the name of a - child controller. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified in - RFC 4646 or ISO 639-2 language code format. - - @param ControllerName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - controller specified by ControllerHandle and - ChildHandle in the language specified by - Language from the point of view of the driver - specified by This. - - @retval EFI_SUCCESS The Unicode string for the user readable name in - the language specified by Language for the - driver specified by This was returned in - DriverName. - - @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. - - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid - EFI_HANDLE. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER ControllerName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This is not currently - managing the controller specified by - ControllerHandle and ChildHandle. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -NvmExpressComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ) -{ - EFI_STATUS Status; - EFI_BLOCK_IO_PROTOCOL *BlockIo; - NVME_DEVICE_PRIVATE_DATA *Device; - EFI_UNICODE_STRING_TABLE *ControllerNameTable; - - // - // Make sure this driver is currently managing ControllHandle - // - Status = EfiTestManagedDevice ( - ControllerHandle, - gNvmExpressDriverBinding.DriverBindingHandle, - &gEfiPciIoProtocolGuid - ); - if (EFI_ERROR (Status)) { - return Status; - } - - ControllerNameTable = mNvmExpressControllerNameTable; - if (ChildHandle != NULL) { - Status = EfiTestChildHandle ( - ControllerHandle, - ChildHandle, - &gEfiNvmExpressPassThruProtocolGuid - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get the child context - // - Status = gBS->OpenProtocol ( - ChildHandle, - &gEfiBlockIoProtocolGuid, - (VOID **)&BlockIo, - gNvmExpressDriverBinding.DriverBindingHandle, - ChildHandle, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo); - ControllerNameTable = Device->ControllerNameTable; - } - - return LookupUnicodeString2 ( - Language, - This->SupportedLanguages, - ControllerNameTable, - ControllerName, - (BOOLEAN)(This == &gNvmExpressComponentName) - ); -} diff --git a/MsvmPkg/NvmExpressDxe/NvmExpress.c b/MsvmPkg/NvmExpressDxe/NvmExpress.c deleted file mode 100644 index 93f958524..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpress.c +++ /dev/null @@ -1,1817 +0,0 @@ -/** @file - NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows - NVM Express specification. - - Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.
- Copyright (c) Microsoft Corporation.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "NvmExpress.h" -#include "NvmExpressBounce.h" // MS_HYP_CHANGE - -// -// NVM Express Driver Binding Protocol Instance -// -EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding = { - NvmExpressDriverBindingSupported, - NvmExpressDriverBindingStart, - NvmExpressDriverBindingStop, - 0x10, - NULL, - NULL -}; - -// -// NVM Express EFI Driver Supported EFI Version Protocol Instance -// -EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion = { - sizeof (EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL), // Size of Protocol structure. - 0 // Version number to be filled at start up. -}; - -// -// Template for NVM Express Pass Thru Mode data structure. -// -GLOBAL_REMOVE_IF_UNREFERENCED EFI_NVM_EXPRESS_PASS_THRU_MODE gEfiNvmExpressPassThruMode = { - EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | - EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL | - EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_NONBLOCKIO | - EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_CMD_SET_NVM, - sizeof (UINTN), - 0x10100 -}; - -/** - Check if the specified Nvm Express device namespace is active, and create child handles - for them with BlockIo and DiskInfo protocol instances. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @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. - - @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated. - @return Others Some error occurs when enumerating the namespaces. - -**/ -EFI_STATUS -EnumerateNvmeDevNamespace ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - UINT32 NamespaceId - ) -{ - NVME_ADMIN_NAMESPACE_DATA *NamespaceData; - EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_HANDLE DeviceHandle; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; - NVME_DEVICE_PRIVATE_DATA *Device; - EFI_STATUS Status; - UINT32 Lbads; - UINT32 Flbas; - UINT32 LbaFmtIdx; - UINT8 Sn[21]; - UINT8 Mn[41]; - VOID *DummyInterface; - - NewDevicePathNode = NULL; - DevicePath = NULL; - Device = NULL; - - // - // Allocate a buffer for Identify Namespace data - // - NamespaceData = AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA)); - if (NamespaceData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - ParentDevicePath = Private->ParentDevicePath; - // - // Identify Namespace - // - Status = NvmeIdentifyNamespace ( - Private, - NamespaceId, - (VOID *)NamespaceData - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - - // - // Validate Namespace - // - if (NamespaceData->Ncap == 0) { - Status = EFI_DEVICE_ERROR; - } else { - // - // allocate device private data for each discovered namespace - // - Device = AllocateZeroPool (sizeof (NVME_DEVICE_PRIVATE_DATA)); - if (Device == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - // - // Initialize SSD namespace instance data - // - Device->Signature = NVME_DEVICE_PRIVATE_DATA_SIGNATURE; - Device->NamespaceId = NamespaceId; - Device->NamespaceUuid = NamespaceData->Eui64; - - Device->ControllerHandle = Private->ControllerHandle; - Device->DriverBindingHandle = Private->DriverBindingHandle; - 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.IoAlign = Private->PassThruMode.IoAlign; - - Flbas = NamespaceData->Flbas; - LbaFmtIdx = Flbas & 0xF; - - // - // Currently this NVME driver only suport Metadata Size == 0 - // - if (NamespaceData->LbaFormat[LbaFmtIdx].Ms != 0) { - DEBUG (( - DEBUG_ERROR, - "NVME IDENTIFY NAMESPACE [%d] Ms(%d) is not supported.\n", - NamespaceId, - NamespaceData->LbaFormat[LbaFmtIdx].Ms - )); - Status = EFI_UNSUPPORTED; - goto Exit; - } - - Lbads = NamespaceData->LbaFormat[LbaFmtIdx].Lbads; - Device->Media.BlockSize = (UINT32)1 << Lbads; - - Device->Media.LastBlock = NamespaceData->Nsze - 1; - Device->Media.LogicalBlocksPerPhysicalBlock = 1; - Device->Media.LowestAlignedLba = 1; - - // - // Create BlockIo Protocol instance - // - Device->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION2; - Device->BlockIo.Media = &Device->Media; - Device->BlockIo.Reset = NvmeBlockIoReset; - Device->BlockIo.ReadBlocks = NvmeBlockIoReadBlocks; - Device->BlockIo.WriteBlocks = NvmeBlockIoWriteBlocks; - Device->BlockIo.FlushBlocks = NvmeBlockIoFlushBlocks; - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - if (NVME_SUPPORT_BLOCKIO2 (Private)) { - // We have multiple data queues, so we can support the BlockIo2 protocol - - // Create BlockIo2 Protocol instance - Device->BlockIo2.Media = &Device->Media; - Device->BlockIo2.Reset = NvmeBlockIoResetEx; - Device->BlockIo2.ReadBlocksEx = NvmeBlockIoReadBlocksEx; - Device->BlockIo2.WriteBlocksEx = NvmeBlockIoWriteBlocksEx; - Device->BlockIo2.FlushBlocksEx = NvmeBlockIoFlushBlocksEx; - } - - // MU_CHANGE [END] - Request Number of Queues from Controller - - 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; - Device->StorageSecurity.SendData = NvmeStorageSecuritySendData; - - // - // Create DiskInfo Protocol instance - // - CopyMem (&Device->NamespaceData, NamespaceData, sizeof (NVME_ADMIN_NAMESPACE_DATA)); - InitializeDiskInfo (Device); - - // - // Create a Nvm Express Namespace Device Path Node - // - Status = Private->Passthru.BuildDevicePath ( - &Private->Passthru, - Device->NamespaceId, - &NewDevicePathNode - ); - - if (EFI_ERROR (Status)) { - goto Exit; - } - - // - // Append the SSD node to the controller's device path - // - DevicePath = AppendDevicePathNode (ParentDevicePath, NewDevicePathNode); - if (DevicePath == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - DeviceHandle = NULL; - RemainingDevicePath = DevicePath; - Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle); - if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd (RemainingDevicePath)) { - Status = EFI_ALREADY_STARTED; - FreePool (DevicePath); - goto Exit; - } - - Device->DevicePath = DevicePath; - - // - // Make sure the handle is NULL so we create a new handle - // - Device->DeviceHandle = NULL; - - Status = gBS->InstallMultipleProtocolInterfaces ( - &Device->DeviceHandle, - &gEfiDevicePathProtocolGuid, - Device->DevicePath, - &gEfiBlockIoProtocolGuid, - &Device->BlockIo, - // &gEfiBlockIo2ProtocolGuid, // MU_CHANGE - Request Number of Queues from Controller - // &Device->BlockIo2, // MU_CHANGE - Request Number of Queues from Controller - &gEfiDiskInfoProtocolGuid, - &Device->DiskInfo, - &gMediaSanitizeProtocolGuid, - &Device->MediaSanitize, - NULL - ); - - if (EFI_ERROR (Status)) { - goto Exit; - } - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - if (NVME_SUPPORT_BLOCKIO2 (Private)) { - // We have multiple data queues, so we can support the BlockIo2 protocol - Status = gBS->InstallMultipleProtocolInterfaces ( - &Device->DeviceHandle, - &gEfiBlockIo2ProtocolGuid, - &Device->BlockIo2, - NULL - ); - - if (EFI_ERROR (Status)) { - gBS->UninstallMultipleProtocolInterfaces ( - Device->DeviceHandle, - &gEfiDevicePathProtocolGuid, - Device->DevicePath, - &gEfiBlockIoProtocolGuid, - &Device->BlockIo, - &gEfiDiskInfoProtocolGuid, - &Device->DiskInfo, - NULL - ); - - DEBUG ((DEBUG_ERROR, "%a: Failed to install BlockIo2 protocol. Error %r\n", __func__, Status)); - ASSERT_EFI_ERROR (Status); - goto Exit; - } - } - - // MU_CHANGE [END] - Request Number of Queues from Controller - - // - // Check if the NVMe controller supports the Security Send and Security Receive commands - // - if ((Private->ControllerData->Oacs & SECURITY_SEND_RECEIVE_SUPPORTED) != 0) { - Status = gBS->InstallProtocolInterface ( - &Device->DeviceHandle, - &gEfiStorageSecurityCommandProtocolGuid, - EFI_NATIVE_INTERFACE, - &Device->StorageSecurity - ); - if (EFI_ERROR (Status)) { - gBS->UninstallMultipleProtocolInterfaces ( - Device->DeviceHandle, - &gEfiDevicePathProtocolGuid, - Device->DevicePath, - &gEfiBlockIoProtocolGuid, - &Device->BlockIo, - // &gEfiBlockIo2ProtocolGuid, // MU_CHANGE - Request Number of Queues from Controller - // &Device->BlockIo2, // MU_CHANGE - Request Number of Queues from Controller - &gEfiDiskInfoProtocolGuid, - &Device->DiskInfo, - &gMediaSanitizeProtocolGuid, - &Device->MediaSanitize, - NULL - ); - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - if (NVME_SUPPORT_BLOCKIO2 (Private)) { - // We have multiple data queues, so we need to uninstall the BlockIo2 protocol - gBS->UninstallMultipleProtocolInterfaces ( - Device->DeviceHandle, - &gEfiBlockIo2ProtocolGuid, - &Device->BlockIo2, - NULL - ); - } - - // MU_CHANGE [END] - Request Number of Queues from Controller - - goto Exit; - } - } - - gBS->OpenProtocol ( - Private->ControllerHandle, - &gEfiNvmExpressPassThruProtocolGuid, - (VOID **)&DummyInterface, - Private->DriverBindingHandle, - Device->DeviceHandle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - - // - // Dump NvmExpress Identify Namespace Data - // - DEBUG ((DEBUG_INFO, " == NVME IDENTIFY NAMESPACE [%d] DATA ==\n", NamespaceId)); - DEBUG ((DEBUG_INFO, " NSZE : 0x%lx\n", NamespaceData->Nsze)); - DEBUG ((DEBUG_INFO, " NCAP : 0x%lx\n", NamespaceData->Ncap)); - DEBUG ((DEBUG_INFO, " NUSE : 0x%lx\n", NamespaceData->Nuse)); - DEBUG ((DEBUG_INFO, " LBAF0.LBADS : 0x%x\n", (NamespaceData->LbaFormat[0].Lbads))); - - // - // Build controller name for Component Name (2) protocol. - // - CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn)); - Sn[20] = 0; - CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn)); - Mn[40] = 0; - UnicodeSPrintAsciiFormat (Device->ModelName, sizeof (Device->ModelName), "%a-%a-%lx", Sn, Mn, NamespaceData->Eui64); - - AddUnicodeString2 ( - "eng", - gNvmExpressComponentName.SupportedLanguages, - &Device->ControllerNameTable, - Device->ModelName, - TRUE - ); - - AddUnicodeString2 ( - "en", - gNvmExpressComponentName2.SupportedLanguages, - &Device->ControllerNameTable, - Device->ModelName, - FALSE - ); - } - -Exit: - if (NamespaceData != NULL) { - FreePool (NamespaceData); - } - - if (NewDevicePathNode != NULL) { - FreePool (NewDevicePathNode); - } - - if (EFI_ERROR (Status) && (Device != NULL) && (Device->DevicePath != NULL)) { - FreePool (Device->DevicePath); - } - - if (EFI_ERROR (Status) && (Device != NULL)) { - FreePool (Device); - } - - return Status; -} - -/** - Discover all Nvm Express device namespaces, and create child handles for them with BlockIo - and DiskInfo protocol instances. - - // MU_CHANGE [BEGIN] - NVMe namespace filtering - When PcdNvmeNamespaceFilterId is 0, all namespaces are enumerated. - When non-zero, only the namespace matching the specified NSID is - discovered and enumerated. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param[in] FilterNsId If 0, discover all namespaces. If non-zero, only discover the namespace - with this NSID. - - @retval EFI_SUCCESS All the namespaces in the device are successfully enumerated. - @return Others Some error occurs when enumerating the namespaces. - -**/ -EFI_STATUS -DiscoverAllNamespaces ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT32 FilterNsId - ) -// MU_CHANGE [END] - NVMe namespace filtering -{ - EFI_STATUS Status; - UINT32 NamespaceId; - EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru; - - NamespaceId = 0xFFFFFFFF; - Passthru = &Private->Passthru; - - while (TRUE) { - Status = Passthru->GetNextNamespace ( - Passthru, - (UINT32 *)&NamespaceId - ); - - if (EFI_ERROR (Status)) { - break; - } - - // MU_CHANGE [BEGIN] - NVMe namespace filtering - if ((FilterNsId != 0) && (NamespaceId != FilterNsId)) { - continue; - } - - // MU_CHANGE [END] - NVMe namespace filtering - - Status = EnumerateNvmeDevNamespace ( - Private, - NamespaceId - ); - - if (EFI_ERROR (Status)) { - continue; - } - - // MU_CHANGE [BEGIN] - NVMe namespace filtering - if (FilterNsId != 0) { - break; - } - - // MU_CHANGE [END] - NVMe namespace filtering - } - - return EFI_SUCCESS; -} - -/** - Unregisters a Nvm Express device namespace. - - This function removes the protocols installed on the controller handle and - frees the resources allocated for the namespace. - - @param This The pointer to EFI_DRIVER_BINDING_PROTOCOL instance. - @param Controller The controller handle of the namespace. - @param Handle The child handle. - - @retval EFI_SUCCESS The namespace is successfully unregistered. - @return Others Some error occurs when unregistering the namespace. - -**/ -EFI_STATUS -UnregisterNvmeNamespace ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_HANDLE Handle - ) -{ - EFI_STATUS Status; - EFI_STATUS BlockIo2Status; // MU_CHANGE - Request Number of Queues from Controller - EFI_BLOCK_IO_PROTOCOL *BlockIo; - NVME_DEVICE_PRIVATE_DATA *Device; - EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - VOID *DummyInterface; - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - BlockIo = NULL; - BlockIo2Status = EFI_SUCCESS; - // MU_CHANGE [END] - Request Number of Queues from Controller - - Status = gBS->OpenProtocol ( - Handle, - &gEfiBlockIoProtocolGuid, - (VOID **)&BlockIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (BlockIo); - - // - // Wait for the device's asynchronous I/O queue to become empty. - // - while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&Device->AsyncQueue); - gBS->RestoreTPL (OldTpl); - - if (IsEmpty) { - break; - } - - gBS->Stall (100); - } - - // - // Close the child handle - // - gBS->CloseProtocol ( - Controller, - &gEfiNvmExpressPassThruProtocolGuid, - This->DriverBindingHandle, - Handle - ); - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - // - // If BlockIo2 is installed, uninstall it. - // - if (NVME_SUPPORT_BLOCKIO2 (Device->Controller)) { - BlockIo2Status = gBS->UninstallMultipleProtocolInterfaces ( - Handle, - &gEfiBlockIo2ProtocolGuid, - &Device->BlockIo2, - NULL - ); - - if (EFI_ERROR (BlockIo2Status)) { - DEBUG ((DEBUG_ERROR, "%a: Failed to uninstall BlockIo2 protocol\n", __func__)); - } - } - - // MU_CHANGE [END] - Request Number of Queues from Controller - // - // The Nvm Express driver installs the BlockIo and DiskInfo in the DriverBindingStart(). - // Here should uninstall both of them. - // - Status = gBS->UninstallMultipleProtocolInterfaces ( - Handle, - &gEfiDevicePathProtocolGuid, - Device->DevicePath, - &gEfiBlockIoProtocolGuid, - &Device->BlockIo, - // &gEfiBlockIo2ProtocolGuid, // MU_CHANGE - Request Number of Queues from Controller - // &Device->BlockIo2, // MU_CHANGE - Request Number of Queues from Controller - &gEfiDiskInfoProtocolGuid, - &Device->DiskInfo, - &gMediaSanitizeProtocolGuid, - &Device->MediaSanitize, - NULL - ); - - if (EFI_ERROR (Status) || EFI_ERROR (BlockIo2Status)) { - // MU_CHANGE - Request Number of Queues from Controller - gBS->OpenProtocol ( - Controller, - &gEfiNvmExpressPassThruProtocolGuid, - (VOID **)&DummyInterface, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - return Status; - } - - // - // If Storage Security Command Protocol is installed, then uninstall this protocol. - // - Status = gBS->OpenProtocol ( - Handle, - &gEfiStorageSecurityCommandProtocolGuid, - (VOID **)&StorageSecurity, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (!EFI_ERROR (Status)) { - Status = gBS->UninstallProtocolInterface ( - Handle, - &gEfiStorageSecurityCommandProtocolGuid, - &Device->StorageSecurity - ); - if (EFI_ERROR (Status)) { - gBS->OpenProtocol ( - Controller, - &gEfiNvmExpressPassThruProtocolGuid, - (VOID **)&DummyInterface, - This->DriverBindingHandle, - Handle, - EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER - ); - return Status; - } - } - - if (Device->DevicePath != NULL) { - FreePool (Device->DevicePath); - } - - if (Device->ControllerNameTable != NULL) { - FreeUnicodeStringTable (Device->ControllerNameTable); - } - - FreePool (Device); - - return EFI_SUCCESS; -} - -/** - Call back function when the timer event is signaled. - - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registered to the - Event. - -**/ -VOID -EFIAPI -ProcessAsyncTaskList ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - EFI_PCI_IO_PROTOCOL *PciIo; - NVME_CQ *Cq; - UINT16 QueueId; - UINT32 Data; - LIST_ENTRY *Link; - LIST_ENTRY *NextLink; - NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; - NVME_BLKIO2_SUBTASK *Subtask; - NVME_BLKIO2_REQUEST *BlkIo2Request; - EFI_BLOCK_IO2_TOKEN *Token; - BOOLEAN HasNewItem; - EFI_STATUS Status; - // MU_CHANGE - Support alternative hardware queue sizes in NVME driver - UINT16 QueueSize = PcdGetBool (PcdSupportAlternativeQueueSize) ? - NVME_ALTERNATIVE_MAX_QUEUE_SIZE : NVME_ASYNC_CCQ_SIZE; - - Private = (NVME_CONTROLLER_PRIVATE_DATA *)Context; - QueueId = 2; - Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; - HasNewItem = FALSE; - PciIo = Private->PciIo; - - // - // Submit asynchronous subtasks to the NVMe Submission Queue - // - for (Link = GetFirstNode (&Private->UnsubmittedSubtasks); - !IsNull (&Private->UnsubmittedSubtasks, Link); - Link = NextLink) - { - NextLink = GetNextNode (&Private->UnsubmittedSubtasks, Link); - Subtask = NVME_BLKIO2_SUBTASK_FROM_LINK (Link); - BlkIo2Request = Subtask->BlockIo2Request; - Token = BlkIo2Request->Token; - RemoveEntryList (Link); - BlkIo2Request->UnsubmittedSubtaskNum--; - - // - // If any previous subtask fails, do not process subsequent ones. - // - if (Token->TransactionStatus != EFI_SUCCESS) { - if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && - BlkIo2Request->LastSubtaskSubmitted && - (BlkIo2Request->UnsubmittedSubtaskNum == 0)) - { - // - // Remove the BlockIo2 request from the device asynchronous queue. - // - RemoveEntryList (&BlkIo2Request->Link); - FreePool (BlkIo2Request); - gBS->SignalEvent (Token->Event); - } - - FreePool (Subtask->CommandPacket->NvmeCmd); - FreePool (Subtask->CommandPacket->NvmeCompletion); - FreePool (Subtask->CommandPacket); - FreePool (Subtask); - - continue; - } - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - Subtask->NamespaceId, - Subtask->CommandPacket, - Subtask->Event - ); - if (Status == EFI_NOT_READY) { - InsertHeadList (&Private->UnsubmittedSubtasks, Link); - BlkIo2Request->UnsubmittedSubtaskNum++; - break; - } else if (EFI_ERROR (Status)) { - Token->TransactionStatus = EFI_DEVICE_ERROR; - - if (IsListEmpty (&BlkIo2Request->SubtasksQueue) && - Subtask->IsLast) - { - // - // Remove the BlockIo2 request from the device asynchronous queue. - // - RemoveEntryList (&BlkIo2Request->Link); - FreePool (BlkIo2Request); - gBS->SignalEvent (Token->Event); - } - - FreePool (Subtask->CommandPacket->NvmeCmd); - FreePool (Subtask->CommandPacket->NvmeCompletion); - FreePool (Subtask->CommandPacket); - FreePool (Subtask); - } else { - InsertTailList (&BlkIo2Request->SubtasksQueue, Link); - if (Subtask->IsLast) { - BlkIo2Request->LastSubtaskSubmitted = TRUE; - } - } - } - - while (Cq->Pt != Private->Pt[QueueId]) { - ASSERT (Cq->Sqid == QueueId); - - HasNewItem = TRUE; - - // - // Find the command with given Command Id. - // - for (Link = GetFirstNode (&Private->AsyncPassThruQueue); - !IsNull (&Private->AsyncPassThruQueue, Link); - Link = NextLink) - { - NextLink = GetNextNode (&Private->AsyncPassThruQueue, Link); - AsyncRequest = NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link); - if (AsyncRequest->CommandId == Cq->Cid) { - // - // Copy the Respose Queue entry for this command to the callers - // response buffer. - // - CopyMem ( - AsyncRequest->Packet->NvmeCompletion, - Cq, - sizeof (EFI_NVM_EXPRESS_COMPLETION) - ); - - // MS_HYP_CHANGE BEGIN - // Copy back data and release the bounce buffers - - if (AsyncRequest->Packet->NvmeCmd->Cdw0.Opcode & BIT1) { - if (AsyncRequest->TransferBouncePageList != NULL) { - NvmExpressCopyBouncePagesToExternalBuffer ( - AsyncRequest->Packet->TransferBuffer, - AsyncRequest->Packet->TransferLength, - AsyncRequest->TransferBouncePageList, - FALSE - ); - NvmExpressReleaseBouncePages ( - Private, - AsyncRequest->TransferBouncePageList - ); - } - - if (AsyncRequest->MetadataBouncePageList != NULL) { - NvmExpressCopyBouncePagesToExternalBuffer ( - AsyncRequest->Packet->MetadataBuffer, - AsyncRequest->Packet->MetadataLength, - AsyncRequest->MetadataBouncePageList, - FALSE - ); - NvmExpressReleaseBouncePages ( - Private, - AsyncRequest->MetadataBouncePageList - ); - } - } - - // MS_HYP_CHANGE END - - // - // Free the resources allocated before cmd submission - // - if (AsyncRequest->MapData != NULL) { - PciIo->Unmap (PciIo, AsyncRequest->MapData); - } - - if (AsyncRequest->MapMeta != NULL) { - PciIo->Unmap (PciIo, AsyncRequest->MapMeta); - } - - if (AsyncRequest->MapPrpList != NULL) { - PciIo->Unmap (PciIo, AsyncRequest->MapPrpList); - } - - if (AsyncRequest->PrpListHost != NULL) { - // MS_HYP_CHANGE BEGIN - if (IsIsolated ()) { - NvmExpressMakeAddressRangePrivate (&AsyncRequest->PrpListHostVisibilityContext, AsyncRequest->PrpListHost); - } - - // MS_HYP_CHANGE END - - PciIo->FreeBuffer ( - PciIo, - AsyncRequest->PrpListNo, - AsyncRequest->PrpListHost - ); - } - - RemoveEntryList (Link); - gBS->SignalEvent (AsyncRequest->CallerEvent); - FreePool (AsyncRequest); - - // - // Update submission queue head. - // - Private->AsyncSqHead = Cq->Sqhd; - break; - } - } - - Private->CqHdbl[QueueId].Cqh++; - // MU_CHANGE - Support alternative hardware queue sizes in NVME driver - if (Private->CqHdbl[QueueId].Cqh > MIN (QueueSize, Private->Cap.Mqes)) { - Private->CqHdbl[QueueId].Cqh = 0; - Private->Pt[QueueId] ^= 1; - } - - Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; - } - - if (HasNewItem) { - Data = ReadUnaligned32 ((UINT32 *)&Private->CqHdbl[QueueId]); - PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_CQHDBL_OFFSET (QueueId, Private->Cap.Dstrd), - 1, - &Data - ); - } -} - -/** - Tests to see if this driver supports a given controller. If a child device is provided, - it further tests to see if this driver supports creating a handle for the specified child device. - - This function checks to see if the driver specified by This supports the device specified by - ControllerHandle. Drivers will typically use the device path attached to - ControllerHandle and/or the services from the bus I/O abstraction attached to - ControllerHandle to determine if the driver supports ControllerHandle. This function - may be called many times during platform initialization. In order to reduce boot times, the tests - performed by this function must be very small, and take as little time as possible to execute. This - function must not change the state of any hardware devices, and this function must be aware that the - device specified by ControllerHandle may already be managed by the same driver or a - different driver. This function must match its calls to AllocatePages() with FreePages(), - AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). - Since ControllerHandle may have been previously started by the same driver, if a protocol is - already in the opened state, then it must not be closed with CloseProtocol(). This is required - to guarantee the state of ControllerHandle is not modified by this function. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to test. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For bus drivers, if this parameter is not NULL, then - the bus driver must determine if the bus controller specified - by ControllerHandle and the child controller specified - by RemainingDevicePath are both supported by this - bus driver. - - @retval EFI_SUCCESS The device specified by ControllerHandle and - RemainingDevicePath is supported by the driver specified by This. - @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by the driver - specified by This. - @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by a different - driver or an application that requires exclusive access. - Currently not implemented. - @retval EFI_UNSUPPORTED The device specified by ControllerHandle and - RemainingDevicePath is not supported by the driver specified by This. -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_DEV_PATH_PTR DevicePathNode; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT8 ClassCode[3]; - - // - // Check whether device path is valid - // - if (RemainingDevicePath != NULL) { - // - // Check if RemainingDevicePath is the End of Device Path Node, - // if yes, go on checking other conditions - // - if (!IsDevicePathEnd (RemainingDevicePath)) { - // - // If RemainingDevicePath isn't the End of Device Path Node, - // check its validation - // - DevicePathNode.DevPath = RemainingDevicePath; - - if ((DevicePathNode.DevPath->Type != MESSAGING_DEVICE_PATH) || - (DevicePathNode.DevPath->SubType != MSG_NVME_NAMESPACE_DP) || - (DevicePathNodeLength (DevicePathNode.DevPath) != sizeof (NVME_NAMESPACE_DEVICE_PATH))) - { - return EFI_UNSUPPORTED; - } - } - } - - // - // Open the EFI Device Path protocol needed to perform the supported test - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **)&ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Close protocol, don't use device path protocol in the Support() function - // - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - // - // Attempt to Open PCI I/O Protocol - // - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **)&PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if (Status == EFI_ALREADY_STARTED) { - return EFI_SUCCESS; - } - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Now further check the PCI header: Base class (offset 0x0B) and Sub Class (offset 0x0A). - // This controller should be a Nvm Express controller. - // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint8, - PCI_CLASSCODE_OFFSET, - sizeof (ClassCode), - ClassCode - ); - if (EFI_ERROR (Status)) { - goto Done; - } - - // - // Examine Nvm Express controller PCI Configuration table fields - // - if ((ClassCode[0] != PCI_IF_NVMHCI) || (ClassCode[1] != PCI_CLASS_MASS_STORAGE_NVM) || (ClassCode[2] != PCI_CLASS_MASS_STORAGE)) { - Status = EFI_UNSUPPORTED; - } - -Done: - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - return Status; -} - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Unmap the queues from PciIo and free the buffers allocated. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS The queues are successfully cleaned up. - @return Others Some error occurs when cleaning up the queues. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverCleanUpQueues ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - EFI_STATUS Status; - EFI_STATUS ReturnStatus; - UINTN QueuePairPageCount; - - ReturnStatus = EFI_SUCCESS; - - if (Private == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Admin Queue Clean-up - // - if (Private->Mapping != NULL) { - Status = Private->PciIo->Unmap (Private->PciIo, Private->Mapping); - if (EFI_ERROR (Status)) { - ReturnStatus = Status; - DEBUG ((DEBUG_ERROR, "%a: Unmap Admin Queue Mapping failed %r\n", __func__, Status)); - ASSERT_EFI_ERROR (Status); - } - - Private->Mapping = NULL; - } - - if (Private->Buffer != NULL) { - QueuePairPageCount = NVME_SQ_SIZE_IN_PAGES (Private, 0) + NVME_CQ_SIZE_IN_PAGES (Private, 0); - - // MS_HYP_CHANGE BEGIN - if (IsIsolated ()) { - NvmExpressMakeAddressRangePrivate (&Private->QueueVisibilityContext, Private->Buffer); - - } - // MS_HYP_CHANGE END - - Status = Private->PciIo->FreeBuffer (Private->PciIo, QueuePairPageCount, Private->Buffer); - - if (EFI_ERROR (Status)) { - ReturnStatus = Status; - DEBUG ((DEBUG_ERROR, "%a: FreeBuffer Buffer failed %r\n", __func__, Status)); - ASSERT_EFI_ERROR (Status); - } - - Private->Buffer = NULL; - } - - // - // I/O Queue Clean-up - // - if (Private->IoQueueMapping != NULL) { - Status = Private->PciIo->Unmap (Private->PciIo, Private->IoQueueMapping); - - if (EFI_ERROR (Status)) { - ReturnStatus = Status; - DEBUG ((DEBUG_ERROR, "%a: Unmap IoQueueMapping failed %r\n", __func__, Status)); - ASSERT_EFI_ERROR (Status); - } - - Private->IoQueueMapping = NULL; - } - - if (Private->IoQueueBuffer != NULL) { - // Using the first data queue size for the number of pages required for the data queues - QueuePairPageCount = NVME_SQ_SIZE_IN_PAGES (Private, 1) + NVME_CQ_SIZE_IN_PAGES (Private, 1); - - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) { - NvmExpressMakeAddressRangePrivate (&Private->IoQueueVisibilityContext, Private->IoQueueBuffer); - } - // MS_HYP_CHANGE END - Status = Private->PciIo->FreeBuffer (Private->PciIo, QueuePairPageCount*Private->NumberOfIoQueuePairs, Private->IoQueueBuffer); - - if (EFI_ERROR (Status)) { - ReturnStatus = Status; - DEBUG ((DEBUG_ERROR, "%a: FreeBuffer IoQueueBuffer failed %r\n", __func__, Status)); - ASSERT_EFI_ERROR (Status); - } - - Private->IoQueueBuffer = NULL; - } - - return ReturnStatus; -} - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -/** - Starts a device controller or a bus controller. - - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For a bus driver, if this parameter is NULL, then handles - for all the children of Controller are created by this driver. - If this parameter is not NULL and the first Device Path Node is - not the End of Device Path Node, then only the handle for the - child device specified by the first Device Path Node of - RemainingDevicePath is created by this driver. - If the first Device Path Node of RemainingDevicePath is - the End of Device Path Node, no child handle is created by this - driver. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - NVME_CONTROLLER_PRIVATE_DATA *Private; - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - UINT32 NamespaceId; - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // EFI_PHYSICAL_ADDRESS MappedAddr; - // UINTN Bytes; - // MU_CHANGE [END] - Allocate IO Queue Buffer - - EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *Passthru; - UINT32 FilterNsId; // MU_CHANGE - NVMe namespace filtering - - - DEBUG ((DEBUG_INFO, "NvmExpressDriverBindingStart: start\n")); - - Private = NULL; - Passthru = NULL; - ParentDevicePath = NULL; - - Status = gBS->OpenProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - (VOID **)&ParentDevicePath, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { - return Status; - } - - Status = gBS->OpenProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - (VOID **)&PciIo, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_BY_DRIVER - ); - - if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { - return Status; - } - - // - // Check EFI_ALREADY_STARTED to reuse the original NVME_CONTROLLER_PRIVATE_DATA. - // - if (Status != EFI_ALREADY_STARTED) { - Private = AllocateZeroPool (sizeof (NVME_CONTROLLER_PRIVATE_DATA)); - - if (Private == NULL) { - DEBUG ((DEBUG_ERROR, "NvmExpressDriverBindingStart: allocating pool for Nvme Private Data failed!\n")); - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - // - // Save original PCI attributes - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationGet, - 0, - &Private->PciAttributes - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Enable 64-bit DMA support in the PCI layer. - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE, - NULL - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "NvmExpressDriverBindingStart: failed to enable 64-bit DMA (%r)\n", Status)); - } - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // // - // // 6 x 4kB aligned buffers will be carved out of this buffer. - // // 1st 4kB boundary is the start of the admin submission queue. - // // 2nd 4kB boundary is the start of the admin completion queue. - // // 3rd 4kB boundary is the start of I/O submission queue #1. - // // 4th 4kB boundary is the start of I/O completion queue #1. - // // 5th 4kB boundary is the start of I/O submission queue #2. - // // 6th 4kB boundary is the start of I/O completion queue #2. - // // - // // Allocate 6 pages of memory, then map it for bus master read and write. - // // - // Status = PciIo->AllocateBuffer ( - // PciIo, - // AllocateAnyPages, - // EfiBootServicesData, - // 6, - // (VOID **)&Private->Buffer, - // 0 - // ); - // if (EFI_ERROR (Status)) { - // goto Exit; - // } - - - // MS_HYP_CHANGE - Support alternative hardware queue sizes in NVME driver - // Bytes = EFI_PAGES_TO_SIZE (QueuePageCount); - // Status = PciIo->Map ( - // PciIo, - // EfiPciIoOperationBusMasterCommonBuffer, - // Private->Buffer, - // &Bytes, - // &MappedAddr, - // &Private->Mapping - // ); - - // MS_HYP_CHANGE - Support alternative hardware queue sizes in NVME driver - // if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (QueuePageCount))) { - // goto Exit; - // } - - - // Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr; - // MU_CHANGE [END] - Allocate IO Queue Buffer - - Private->Signature = NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE; - Private->ControllerHandle = Controller; - Private->ImageHandle = This->DriverBindingHandle; - Private->DriverBindingHandle = This->DriverBindingHandle; - Private->PciIo = PciIo; - Private->ParentDevicePath = ParentDevicePath; - Private->Passthru.Mode = &Private->PassThruMode; - Private->Passthru.PassThru = NvmExpressPassThru; - Private->Passthru.GetNextNamespace = NvmExpressGetNextNamespace; - Private->Passthru.BuildDevicePath = NvmExpressBuildDevicePath; - Private->Passthru.GetNamespace = NvmExpressGetNamespace; - CopyMem (&Private->PassThruMode, &gEfiNvmExpressPassThruMode, sizeof (EFI_NVM_EXPRESS_PASS_THRU_MODE)); - InitializeListHead (&Private->AsyncPassThruQueue); - InitializeListHead (&Private->UnsubmittedSubtasks); - - // MS_HYP_CHANGE BEGIN - // - // Allocate bounce block for isolated VMs - // - - if (NvmExpressIsBounceActive ()) { - InitializeListHead (&Private->BounceBlockListHead); - Status = NvmExpressAllocateBounceBlock (Private, NVME_BOUNCE_BLOCK_SIZE); - if (EFI_ERROR (Status)) { - goto Exit; - } - } - - // MS_HYP_CHANGE END - - Status = NvmeControllerInit (Private); - if (EFI_ERROR (Status)) { - goto Exit; - } - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - - // - // Start the asynchronous I/O completion monitor - // The ProcessAsyncTaskList event and NVME_HC_ASYNC_TIMER timer are only used for the BlockIo2 protocol, - // which is only installed when the number of IO queues is greater than 1 - // - if (NVME_SUPPORT_BLOCKIO2 (Private)) { - Status = gBS->CreateEvent ( - EVT_TIMER | EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - ProcessAsyncTaskList, - Private, - &Private->TimerEvent - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - - Status = gBS->SetTimer ( - Private->TimerEvent, - TimerPeriodic, - NVME_HC_ASYNC_TIMER - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - } - - // MU_CHANGE [END] - Request Number of Queues from Controller - - Status = gBS->InstallMultipleProtocolInterfaces ( - &Controller, - &gEfiNvmExpressPassThruProtocolGuid, - &Private->Passthru, - NULL - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - - NvmeRegisterShutdownNotification (); - } else { - Status = gBS->OpenProtocol ( - Controller, - &gEfiNvmExpressPassThruProtocolGuid, - (VOID **)&Passthru, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - goto Exit; - } - - Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (Passthru); - } - - // MU_CHANGE [BEGIN] - NVMe namespace filtering - FilterNsId = PcdGet32 (PcdNvmeNamespaceFilterId); - // MU_CHANGE [END] - NVMe namespace filtering - - if (RemainingDevicePath == NULL) { - // - // Enumerate all NVME namespaces in the controller - // - // MU_CHANGE [BEGIN] - NVMe namespace filtering - Status = DiscoverAllNamespaces ( - Private, - FilterNsId - ); - // MU_CHANGE [END] - NVMe namespace filtering - } else if (!IsDevicePathEnd (RemainingDevicePath)) { - // - // Enumerate the specified NVME namespace - // - Status = Private->Passthru.GetNamespace ( - &Private->Passthru, - RemainingDevicePath, - &NamespaceId - ); - - if (!EFI_ERROR (Status)) { - // MU_CHANGE [BEGIN] - NVMe namespace filtering - if ((FilterNsId == 0) || - (NamespaceId == FilterNsId)) - { - Status = EnumerateNvmeDevNamespace ( - Private, - NamespaceId - ); - } - - // MU_CHANGE [END] - NVMe namespace filtering - } - } - - DEBUG ((DEBUG_INFO, "NvmExpressDriverBindingStart: end successfully\n")); - return EFI_SUCCESS; - -Exit: - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // if ((Private != NULL) && (Private->Mapping != NULL)) { - // PciIo->Unmap (PciIo, Private->Mapping); - // } - // - // if ((Private != NULL) && (Private->Buffer != NULL)) { - // PciIo->FreeBuffer (PciIo, 6, Private->Buffer); - // } - - Status = NvmExpressDriverCleanUpQueues (Private); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: NvmExpressDriverCleanUpQueues failed %r\n", __func__, Status)); - } - - // MU_CHANGE [END] - Allocate IO Queue Buffer - - if ((Private != NULL) && (Private->ControllerData != NULL)) { - FreePool (Private->ControllerData); - } - - if (Private != NULL) { - if (Private->TimerEvent != NULL) { - gBS->CloseEvent (Private->TimerEvent); - } - - FreePool (Private); - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - DEBUG ((DEBUG_INFO, "NvmExpressDriverBindingStart: end with %r\n", Status)); - - return Status; -} - -/** - Stops a device controller or a bus controller. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ) -{ - EFI_STATUS Status; - BOOLEAN AllChildrenStopped; - UINTN Index; - NVME_CONTROLLER_PRIVATE_DATA *Private; - EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *PassThru; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - - if (NumberOfChildren == 0) { - Status = gBS->OpenProtocol ( - Controller, - &gEfiNvmExpressPassThruProtocolGuid, - (VOID **)&PassThru, - This->DriverBindingHandle, - Controller, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - - if (!EFI_ERROR (Status)) { - Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (PassThru); - - // - // Wait for the asynchronous PassThru queue to become empty. - // - while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&Private->AsyncPassThruQueue) && - IsListEmpty (&Private->UnsubmittedSubtasks); - gBS->RestoreTPL (OldTpl); - - if (IsEmpty) { - break; - } - - gBS->Stall (100); - } - - gBS->UninstallMultipleProtocolInterfaces ( - Controller, - &gEfiNvmExpressPassThruProtocolGuid, - PassThru, - NULL - ); - - if (Private->TimerEvent != NULL) { - gBS->CloseEvent (Private->TimerEvent); - } - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // if (Private->Mapping != NULL) { - // Private->PciIo->Unmap (Private->PciIo, Private->Mapping); - // } - // - // if (Private->Buffer != NULL) { - // Private->PciIo->FreeBuffer (Private->PciIo, 6, Private->Buffer); - // } - - Status = NvmExpressDriverCleanUpQueues (Private); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: NvmExpressDriverCleanUpQueues failed %r\n", __func__, Status)); - } - - // MU_CHANGE [END] - Allocate IO Queue Buffer - - NvmExpressFreeAllBounceBlocks (Private); // MS_HYP_CHANGE - FreePool (Private->ControllerData); - FreePool (Private); - } - - gBS->CloseProtocol ( - Controller, - &gEfiPciIoProtocolGuid, - This->DriverBindingHandle, - Controller - ); - gBS->CloseProtocol ( - Controller, - &gEfiDevicePathProtocolGuid, - This->DriverBindingHandle, - Controller - ); - - NvmeUnregisterShutdownNotification (); - - return EFI_SUCCESS; - } - - AllChildrenStopped = TRUE; - - for (Index = 0; Index < NumberOfChildren; Index++) { - Status = UnregisterNvmeNamespace (This, Controller, ChildHandleBuffer[Index]); - if (EFI_ERROR (Status)) { - AllChildrenStopped = FALSE; - } - } - - if (!AllChildrenStopped) { - return EFI_DEVICE_ERROR; - } - - return EFI_SUCCESS; -} - -/** - This is the unload handle for the NVM Express driver. - - Disconnect the driver specified by ImageHandle from the NVMe device in the handle database. - Uninstall all the protocols installed in the driver. - - @param[in] ImageHandle The drivers' driver image. - - @retval EFI_SUCCESS The image is unloaded. - @retval Others Failed to unload the image. - -**/ -EFI_STATUS -EFIAPI -NvmExpressUnload ( - IN EFI_HANDLE ImageHandle - ) -{ - EFI_STATUS Status; - EFI_HANDLE *DeviceHandleBuffer; - UINTN DeviceHandleCount; - UINTN Index; - EFI_COMPONENT_NAME_PROTOCOL *ComponentName; - EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2; - - // - // Get the list of the device handles managed by this driver. - // If there is an error getting the list, then means the driver - // doesn't manage any device. At this way, we would only close - // those protocols installed at image handle. - // - DeviceHandleBuffer = NULL; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiNvmExpressPassThruProtocolGuid, - NULL, - &DeviceHandleCount, - &DeviceHandleBuffer - ); - - if (!EFI_ERROR (Status)) { - // - // Disconnect the driver specified by ImageHandle from all - // the devices in the handle database. - // - for (Index = 0; Index < DeviceHandleCount; Index++) { - Status = gBS->DisconnectController ( - DeviceHandleBuffer[Index], - ImageHandle, - NULL - ); - if (EFI_ERROR (Status)) { - goto EXIT; - } - } - } - - // - // Uninstall all the protocols installed in the driver entry point - // - Status = gBS->UninstallMultipleProtocolInterfaces ( - ImageHandle, - &gEfiDriverBindingProtocolGuid, - &gNvmExpressDriverBinding, - &gEfiDriverSupportedEfiVersionProtocolGuid, - &gNvmExpressDriverSupportedEfiVersion, - NULL - ); - - if (EFI_ERROR (Status)) { - goto EXIT; - } - - // - // Note we have to one by one uninstall the following protocols. - // It's because some of them are optionally installed based on - // the following PCD settings. - // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable - // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable - // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable - // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable - // - Status = gBS->HandleProtocol ( - ImageHandle, - &gEfiComponentNameProtocolGuid, - (VOID **)&ComponentName - ); - if (!EFI_ERROR (Status)) { - gBS->UninstallProtocolInterface ( - ImageHandle, - &gEfiComponentNameProtocolGuid, - ComponentName - ); - } - - Status = gBS->HandleProtocol ( - ImageHandle, - &gEfiComponentName2ProtocolGuid, - (VOID **)&ComponentName2 - ); - if (!EFI_ERROR (Status)) { - gBS->UninstallProtocolInterface ( - ImageHandle, - &gEfiComponentName2ProtocolGuid, - ComponentName2 - ); - } - - Status = EFI_SUCCESS; - -EXIT: - // - // Free the buffer containing the list of handles from the handle database - // - if (DeviceHandleBuffer != NULL) { - gBS->FreePool (DeviceHandleBuffer); - } - - return Status; -} - -/** - The entry point for Nvm Express driver, used to install Nvm Express driver on the ImageHandle. - - @param ImageHandle The firmware allocated handle for this driver image. - @param SystemTable Pointer to the EFI system table. - - @retval EFI_SUCCESS Driver loaded. - @retval other Driver not loaded. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverEntry ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - - Status = EfiLibInstallDriverBindingComponentName2 ( - ImageHandle, - SystemTable, - &gNvmExpressDriverBinding, - ImageHandle, - &gNvmExpressComponentName, - &gNvmExpressComponentName2 - ); - ASSERT_EFI_ERROR (Status); - - // - // Install EFI Driver Supported EFI Version Protocol required for - // EFI drivers that are on PCI and other plug in cards. - // - gNvmExpressDriverSupportedEfiVersion.FirmwareVersion = 0x00020028; - Status = gBS->InstallMultipleProtocolInterfaces ( - &ImageHandle, - &gEfiDriverSupportedEfiVersionProtocolGuid, - &gNvmExpressDriverSupportedEfiVersion, - NULL - ); - ASSERT_EFI_ERROR (Status); - - // MS_HYP_CHANGE BEGIN - if (NvmExpressIsBounceActive ()) { - Status = NvmExpressInitializeBounce (); - ASSERT_EFI_ERROR (Status); - } - - // MS_HYP_CHANGE END - - return Status; -} diff --git a/MsvmPkg/NvmExpressDxe/NvmExpress.h b/MsvmPkg/NvmExpressDxe/NvmExpress.h deleted file mode 100644 index a26582547..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpress.h +++ /dev/null @@ -1,874 +0,0 @@ -/** @file - NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows - NVM Express specification. - - (C) Copyright 2016 Hewlett Packard Enterprise Development LP
- Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.
- Copyright (c) Microsoft Corporation.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef _EFI_NVM_EXPRESS_H_ -#define _EFI_NVM_EXPRESS_H_ - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -typedef struct _NVME_CONTROLLER_PRIVATE_DATA NVME_CONTROLLER_PRIVATE_DATA; -typedef struct _NVME_DEVICE_PRIVATE_DATA NVME_DEVICE_PRIVATE_DATA; -typedef struct _NVME_QUEUE_SIZE_DATA NVME_QUEUE_SIZE_DATA; // MU_CHANGE - Allocate IO Queue Buffer - -#include "NvmExpressBlockIo.h" -#include "NvmExpressBounce.h" // MS_HYP_CHANGE -#include "NvmExpressDiskInfo.h" -#include "NvmExpressHci.h" -#include "NvmExpressMediaSanitize.h" - -extern EFI_DRIVER_BINDING_PROTOCOL gNvmExpressDriverBinding; -extern EFI_COMPONENT_NAME_PROTOCOL gNvmExpressComponentName; -extern EFI_COMPONENT_NAME2_PROTOCOL gNvmExpressComponentName2; -extern EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL gNvmExpressDriverSupportedEfiVersion; - -#define PCI_CLASS_MASS_STORAGE_NVM 0x08 // mass storage sub-class non-volatile memory. -#define PCI_IF_NVMHCI 0x02 // mass storage programming interface NVMHCI. - -#define NVME_ASQ_SIZE 1 // Number of admin submission queue entries, which is 0-based -#define NVME_ACQ_SIZE 1 // Number of admin completion queue entries, which is 0-based - -#define NVME_CSQ_SIZE 1 // Number of I/O submission queue entries, which is 0-based -#define NVME_CCQ_SIZE 1 // Number of I/O completion queue entries, which is 0-based - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer -// NVM Express 2.0e specification, section 5.17.1 Identify Controller Data Structure (CNS 01h) -// The specification defines these numbers as the minimum and standard values. They are what this driver supports. -// The values are in bytes and are reported as a power of 2. -#define NVME_IOSQES_MIN 6 // I/O submission queue entry size -#define NVME_IOCQES_MIN 4 // I/O completion queue entry size -// MU_CHANGE [END] - Allocate IO Queue Buffer - -// -// Number of asynchronous I/O submission queue entries, which is 0-based. -// The asynchronous I/O submission queue size is 4kB in total. -// -#define NVME_ASYNC_CSQ_SIZE 63 -// -// Number of asynchronous I/O completion queue entries, which is 0-based. -// The asynchronous I/O completion queue size is 4kB in total. -// -#define NVME_ASYNC_CCQ_SIZE 255 - -// MU_CHANGE [BEGIN] - Request Number of Queues from Controller -// Maximum number of queue pairs supported by the driver, including the admin queues. -// Queue 0 - Admin -// Queue 1 - Blocking I/O (BlockIo Protocol) -// Queue 2 - Asynchronous I/O (BlockIo2 Protocol) -#define NVME_MAX_QUEUES 3 - -// Returns if the controller supports the BlockIo2 protocol. -// The BlockIo2 protocol is only supported if the controller has more than 1 queue pair allocated -#define NVME_SUPPORT_BLOCKIO2(ContollerPointer) (((ContollerPointer)->NumberOfIoQueuePairs) > 1) -// MU_CHANGE [END] - Request Number of Queues from Controller - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer -// -// Returns the number of pages required for a submission/completion queue -// The Indices are the same as above, 0 for admin, 1 for blocking I/O, 2 for async I/O. -// -#define NVME_SQ_SIZE_IN_PAGES(ControllerPointer, Index) \ - EFI_SIZE_TO_PAGES(((ControllerPointer)->SqData[(Index)].NumberOfEntries * (UINTN)LShiftU64 (2, (ControllerPointer)->SqData[(Index)].EntrySize))) - -#define NVME_CQ_SIZE_IN_PAGES(ControllerPointer, Index) \ - EFI_SIZE_TO_PAGES(((ControllerPointer)->CqData[(Index)].NumberOfEntries * (UINTN)LShiftU64 (2, (ControllerPointer)->CqData[(Index)].EntrySize))) - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -// -// 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 - -// MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - -// -// NVMe DXE to accommodate hardware which requires queue size 255. -// Driver supports queue size up to 255 (4 page SQ buffer). -// DXE driver creates queue size MIN(Cap.Mqes, NVME_MAX_QUEUE_SIZE) for all queues. -// Driver allocates queue buffer to support 255 max queue size. -// Each submission queue buffer is allocated as 64B * 256 = 4 * 4kB = 4 pages. -// Each completion queue buffer is allocated as 16B * 256 = 4kB = 1 page. -// -#define NVME_ALTERNATIVE_MAX_QUEUE_SIZE 255 - -// MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - -#define NVME_CONTROLLER_ID 0 - -// -// MS_HYP_CHANGE: Extended I/O timeout for Azure -#define NVME_GENERIC_TIMEOUT EFI_TIMER_PERIOD_SECONDS (120) - -// -// Nvme async transfer timer interval, set by experience. -// -#define NVME_HC_ASYNC_TIMER EFI_TIMER_PERIOD_MILLISECONDS (1) - -// -// Unique signature for private data structure. -// -#define NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('N','V','M','E') -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer -#define NVME_INVALID_VID_DID 0xFFFF - -// -// Nvme queue data -// -struct _NVME_QUEUE_SIZE_DATA { - UINT32 NumberOfEntries; // in number of entries - UINT8 EntrySize; // in bytes, as a power of 2 -}; - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -// -// Nvme private data structure. -// -struct _NVME_CONTROLLER_PRIVATE_DATA { - UINT32 Signature; - - EFI_HANDLE ControllerHandle; - EFI_HANDLE ImageHandle; - EFI_HANDLE DriverBindingHandle; - - EFI_PCI_IO_PROTOCOL *PciIo; - UINT64 PciAttributes; - - EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; - - EFI_NVM_EXPRESS_PASS_THRU_MODE PassThruMode; - EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL Passthru; - - // - // pointer to identify controller data - // - NVME_ADMIN_CONTROLLER_DATA *ControllerData; - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - // - // Number of Queues Allocated by the controller - // UEFI always uses a 1:1 submission:completion queue allocation so we - // use NumberOfIoQueuePairs to represent the number of data queue pairs allocated. - // NumberOfIoQueuePairs = Nsqa = Ncqa - // - UINT32 NumberOfIoQueuePairs; - // MU_CHANGE [END] - Request Number of Queues from Controller - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // - // Queue Size Data - // - NVME_QUEUE_SIZE_DATA SqData[NVME_MAX_QUEUES]; - NVME_QUEUE_SIZE_DATA CqData[NVME_MAX_QUEUES]; - // MU_CHANGE [END] - Allocate IO Queue Buffer - - // - // 6 x 4kB aligned buffers will be carved out of this buffer. - // 1st 4kB boundary is the start of the admin submission queue. - // 2nd 4kB boundary is the start of the admin completion queue. - // 3rd 4kB boundary is the start of I/O submission queue #1. - // 4th 4kB boundary is the start of I/O completion queue #1. - // 5th 4kB boundary is the start of I/O submission queue #2. - // 6th 4kB boundary is the start of I/O completion queue #2. - // - UINT8 *Buffer; - UINT8 *BufferPciAddr; - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - UINT8 *IoQueueBuffer; - UINT8 *IoQueueBufferPciAddr; - // MU_CHANGE [END] - Allocate IO Queue Buffer - - // - // Pointers to 4kB aligned submission & completion queues. - // - NVME_SQ *SqBuffer[NVME_MAX_QUEUES]; - NVME_CQ *CqBuffer[NVME_MAX_QUEUES]; - NVME_SQ *SqBufferPciAddr[NVME_MAX_QUEUES]; - NVME_CQ *CqBufferPciAddr[NVME_MAX_QUEUES]; - - // - // Submission and completion queue indices. - // - NVME_SQTDBL SqTdbl[NVME_MAX_QUEUES]; - NVME_CQHDBL CqHdbl[NVME_MAX_QUEUES]; - UINT16 AsyncSqHead; - - // - // Flag to indicate internal IO queue creation. - // - BOOLEAN CreateIoQueue; - - UINT8 Pt[NVME_MAX_QUEUES]; - UINT16 Cid[NVME_MAX_QUEUES]; - - // - // Nvme controller capabilities - // - NVME_CAP Cap; - - VOID *Mapping; - VOID *IoQueueMapping; // MU_CHANGE - Allocate IO Queue Buffer - - // - // For Non-blocking operations. - // - EFI_EVENT TimerEvent; - LIST_ENTRY AsyncPassThruQueue; - LIST_ENTRY UnsubmittedSubtasks; - // MS_HYP_CHANGE BEGIN - LIST_ENTRY BounceBlockListHead; - NVME_HOST_VISIBILITY_CONTEXT QueueVisibilityContext; - NVME_HOST_VISIBILITY_CONTEXT IoQueueVisibilityContext; - // MS_HYP_CHANGE END -}; - -#define NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU(a) \ - CR (a, \ - NVME_CONTROLLER_PRIVATE_DATA, \ - Passthru, \ - NVME_CONTROLLER_PRIVATE_DATA_SIGNATURE \ - ) - -// -// Unique signature for private data structure. -// -#define NVME_DEVICE_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('X','S','S','D') - -// -// Nvme device private data structure -// -struct _NVME_DEVICE_PRIVATE_DATA { - UINT32 Signature; - - EFI_HANDLE DeviceHandle; - EFI_HANDLE ControllerHandle; - EFI_HANDLE DriverBindingHandle; - - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - - EFI_UNICODE_STRING_TABLE *ControllerNameTable; - - UINT32 NamespaceId; - UINT64 NamespaceUuid; - - EFI_BLOCK_IO_MEDIA Media; - EFI_BLOCK_IO_PROTOCOL BlockIo; - EFI_BLOCK_IO2_PROTOCOL BlockIo2; - EFI_DISK_INFO_PROTOCOL DiskInfo; - EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity; - - MEDIA_SANITIZE_PROTOCOL MediaSanitize; - - LIST_ENTRY AsyncQueue; - - EFI_LBA NumBlocks; - - CHAR16 ModelName[80]; - NVME_ADMIN_NAMESPACE_DATA NamespaceData; - - NVME_CONTROLLER_PRIVATE_DATA *Controller; -}; - -// -// Statments to retrieve the private data from produced protocols. -// -#define NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO(a) \ - CR (a, \ - NVME_DEVICE_PRIVATE_DATA, \ - BlockIo, \ - NVME_DEVICE_PRIVATE_DATA_SIGNATURE \ - ) - -#define NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2(a) \ - CR (a, \ - NVME_DEVICE_PRIVATE_DATA, \ - BlockIo2, \ - NVME_DEVICE_PRIVATE_DATA_SIGNATURE \ - ) - -#define NVME_DEVICE_PRIVATE_DATA_FROM_DISK_INFO(a) \ - CR (a, \ - NVME_DEVICE_PRIVATE_DATA, \ - DiskInfo, \ - NVME_DEVICE_PRIVATE_DATA_SIGNATURE \ - ) - -#define NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY(a) \ - CR (a, \ - NVME_DEVICE_PRIVATE_DATA, \ - StorageSecurity, \ - 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. -// -#define NVME_BLKIO2_REQUEST_SIGNATURE SIGNATURE_32 ('N', 'B', '2', 'R') - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - - EFI_BLOCK_IO2_TOKEN *Token; - UINTN UnsubmittedSubtaskNum; - BOOLEAN LastSubtaskSubmitted; - // - // The queue for Nvme read/write sub-tasks of a BlockIo2 request. - // - LIST_ENTRY SubtasksQueue; -} NVME_BLKIO2_REQUEST; - -#define NVME_BLKIO2_REQUEST_FROM_LINK(a) \ - CR (a, NVME_BLKIO2_REQUEST, Link, NVME_BLKIO2_REQUEST_SIGNATURE) - -#define NVME_BLKIO2_SUBTASK_SIGNATURE SIGNATURE_32 ('N', 'B', '2', 'S') - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - - BOOLEAN IsLast; - UINT32 NamespaceId; - EFI_EVENT Event; - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *CommandPacket; - // - // The BlockIo2 request this subtask belongs to - // - NVME_BLKIO2_REQUEST *BlockIo2Request; -} NVME_BLKIO2_SUBTASK; - -#define NVME_BLKIO2_SUBTASK_FROM_LINK(a) \ - CR (a, NVME_BLKIO2_SUBTASK, Link, NVME_BLKIO2_SUBTASK_SIGNATURE) - -// -// Nvme asynchronous passthru request. -// -#define NVME_PASS_THRU_ASYNC_REQ_SIG SIGNATURE_32 ('N', 'P', 'A', 'R') - -typedef struct { - UINT32 Signature; - LIST_ENTRY Link; - - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *Packet; - UINT16 CommandId; - VOID *MapPrpList; - UINTN PrpListNo; - VOID *PrpListHost; - VOID *MapData; - VOID *MapMeta; - EFI_EVENT CallerEvent; - // MS_HYP_CHANGE BEGIN - PNVME_BOUNCE_PAGE TransferBouncePageList; - PNVME_BOUNCE_PAGE MetadataBouncePageList; - NVME_HOST_VISIBILITY_CONTEXT PrpListHostVisibilityContext; - // MS_HYP_CHANGE END -} NVME_PASS_THRU_ASYNC_REQ; - -#define NVME_PASS_THRU_ASYNC_REQ_FROM_THIS(a) \ - CR (a, \ - NVME_PASS_THRU_ASYNC_REQ, \ - Link, \ - NVME_PASS_THRU_ASYNC_REQ_SIG \ - ) - -/** - Retrieves a Unicode string that is the user readable name of the driver. - - This function retrieves the user readable name of a driver in the form of a - Unicode string. If the driver specified by This has a user readable name in - the language specified by Language, then a pointer to the driver name is - returned in DriverName, and EFI_SUCCESS is returned. If the driver specified - by This does not support the language specified by Language, - then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified - in RFC 4646 or ISO 639-2 language code format. - - @param DriverName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - driver specified by This in the language - specified by Language. - - @retval EFI_SUCCESS The Unicode string for the Driver specified by - This and the language specified by Language was - returned in DriverName. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER DriverName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -NvmExpressComponentNameGetDriverName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN CHAR8 *Language, - OUT CHAR16 **DriverName - ); - -/** - Retrieves a Unicode string that is the user readable name of the controller - that is being managed by a driver. - - This function retrieves the user readable name of the controller specified by - ControllerHandle and ChildHandle in the form of a Unicode string. If the - driver specified by This has a user readable name in the language specified by - Language, then a pointer to the controller name is returned in ControllerName, - and EFI_SUCCESS is returned. If the driver specified by This is not currently - managing the controller specified by ControllerHandle and ChildHandle, - then EFI_UNSUPPORTED is returned. If the driver specified by This does not - support the language specified by Language, then EFI_UNSUPPORTED is returned. - - @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or - EFI_COMPONENT_NAME_PROTOCOL instance. - - @param ControllerHandle[in] The handle of a controller that the driver - specified by This is managing. This handle - specifies the controller whose name is to be - returned. - - @param ChildHandle[in] The handle of the child controller to retrieve - the name of. This is an optional parameter that - may be NULL. It will be NULL for device - drivers. It will also be NULL for a bus drivers - that wish to retrieve the name of the bus - controller. It will not be NULL for a bus - driver that wishes to retrieve the name of a - child controller. - - @param Language[in] A pointer to a Null-terminated ASCII string - array indicating the language. This is the - language of the driver name that the caller is - requesting, and it must match one of the - languages specified in SupportedLanguages. The - number of languages supported by a driver is up - to the driver writer. Language is specified in - RFC 4646 or ISO 639-2 language code format. - - @param ControllerName[out] A pointer to the Unicode string to return. - This Unicode string is the name of the - controller specified by ControllerHandle and - ChildHandle in the language specified by - Language from the point of view of the driver - specified by This. - - @retval EFI_SUCCESS The Unicode string for the user readable name in - the language specified by Language for the - driver specified by This was returned in - DriverName. - - @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. - - @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid - EFI_HANDLE. - - @retval EFI_INVALID_PARAMETER Language is NULL. - - @retval EFI_INVALID_PARAMETER ControllerName is NULL. - - @retval EFI_UNSUPPORTED The driver specified by This is not currently - managing the controller specified by - ControllerHandle and ChildHandle. - - @retval EFI_UNSUPPORTED The driver specified by This does not support - the language specified by Language. - -**/ -EFI_STATUS -EFIAPI -NvmExpressComponentNameGetControllerName ( - IN EFI_COMPONENT_NAME_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_HANDLE ChildHandle OPTIONAL, - IN CHAR8 *Language, - OUT CHAR16 **ControllerName - ); - -/** - Tests to see if this driver supports a given controller. If a child device is provided, - it further tests to see if this driver supports creating a handle for the specified child device. - - This function checks to see if the driver specified by This supports the device specified by - ControllerHandle. Drivers will typically use the device path attached to - ControllerHandle and/or the services from the bus I/O abstraction attached to - ControllerHandle to determine if the driver supports ControllerHandle. This function - may be called many times during platform initialization. In order to reduce boot times, the tests - performed by this function must be very small, and take as little time as possible to execute. This - function must not change the state of any hardware devices, and this function must be aware that the - device specified by ControllerHandle may already be managed by the same driver or a - different driver. This function must match its calls to AllocatePages() with FreePages(), - AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). - Since ControllerHandle may have been previously started by the same driver, if a protocol is - already in the opened state, then it must not be closed with CloseProtocol(). This is required - to guarantee the state of ControllerHandle is not modified by this function. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to test. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For bus drivers, if this parameter is not NULL, then - the bus driver must determine if the bus controller specified - by ControllerHandle and the child controller specified - by RemainingDevicePath are both supported by this - bus driver. - - @retval EFI_SUCCESS The device specified by ControllerHandle and - RemainingDevicePath is supported by the driver specified by This. - @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by the driver - specified by This. - @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and - RemainingDevicePath is already being managed by a different - driver or an application that requires exclusive access. - Currently not implemented. - @retval EFI_UNSUPPORTED The device specified by ControllerHandle and - RemainingDevicePath is not supported by the driver specified by This. -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverBindingSupported ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Starts a device controller or a bus controller. - - The Start() function is designed to be invoked from the EFI boot service ConnectController(). - As a result, much of the error checking on the parameters to Start() has been moved into this - common boot service. It is legal to call Start() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE. - 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned - EFI_DEVICE_PATH_PROTOCOL. - 3. Prior to calling Start(), the Supported() function for the driver specified by This must - have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle The handle of the controller to start. This handle - must support a protocol interface that supplies - an I/O abstraction to the driver. - @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This - parameter is ignored by device drivers, and is optional for bus - drivers. For a bus driver, if this parameter is NULL, then handles - for all the children of Controller are created by this driver. - If this parameter is not NULL and the first Device Path Node is - not the End of Device Path Node, then only the handle for the - child device specified by the first Device Path Node of - RemainingDevicePath is created by this driver. - If the first Device Path Node of RemainingDevicePath is - the End of Device Path Node, no child handle is created by this - driver. - - @retval EFI_SUCCESS The device was started. - @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval Others The driver failded to start the device. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverBindingStart ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath - ); - -/** - Stops a device controller or a bus controller. - - The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). - As a result, much of the error checking on the parameters to Stop() has been moved - into this common boot service. It is legal to call Stop() from other locations, - but the following calling restrictions must be followed or the system behavior will not be deterministic. - 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this - same driver's Start() function. - 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid - EFI_HANDLE. In addition, all of these handles must have been created in this driver's - Start() function, and the Start() function must have called OpenProtocol() on - ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. - - @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. - @param[in] ControllerHandle A handle to the device being stopped. The handle must - support a bus specific I/O protocol for the driver - to use to stop the device. - @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer. - @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL - if NumberOfChildren is 0. - - @retval EFI_SUCCESS The device was stopped. - @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDriverBindingStop ( - IN EFI_DRIVER_BINDING_PROTOCOL *This, - IN EFI_HANDLE Controller, - IN UINTN NumberOfChildren, - IN EFI_HANDLE *ChildHandleBuffer - ); - -/** - Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports - both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the nonblocking - I/O functionality is optional. - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @param[in] NamespaceId Is a 32 bit Namespace ID to which the Express HCI command packet will be sent. - A value of 0 denotes the NVM Express controller, a value of all 0FFh in the namespace - ID specifies that the command packet should be sent to all valid namespaces. - @param[in,out] Packet A pointer to the NVM Express HCI Command Packet to send to the NVMe namespace specified - by NamespaceId. - @param[in] Event If nonblocking I/O is not supported then Event is ignored, and blocking I/O is performed. - If Event is NULL, then blocking I/O is performed. If Event is not NULL and non blocking I/O - is supported, then nonblocking I/O is performed, and Event will be signaled when the NVM - Express Command Packet completes. - - @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred - to, or from DataBuffer. - @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred - is returned in TransferLength. - @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller - may retry again later. - @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet. - @retval EFI_INVALID_PARAMETER Namespace, or the contents of EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM - Express Command Packet was not sent, so no additional status information is available. - @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the host adapter. - The NVM Express Command Packet was not sent, so no additional status information is available. - @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute. - -**/ -EFI_STATUS -EFIAPI -NvmExpressPassThru ( - 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 - ); - -/** - Used to retrieve the next namespace ID for this NVM Express controller. - - The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves the next valid - namespace ID on this NVM Express controller. - - If on input the value pointed to by NamespaceId is 0xFFFFFFFF, then the first valid namespace - ID defined on the NVM Express controller is returned in the location pointed to by NamespaceId - and a status of EFI_SUCCESS is returned. - - If on input the value pointed to by NamespaceId is an invalid namespace ID other than 0xFFFFFFFF, - then EFI_INVALID_PARAMETER is returned. - - If on input the value pointed to by NamespaceId is a valid namespace ID, then the next valid - namespace ID on the NVM Express controller is returned in the location pointed to by NamespaceId, - and EFI_SUCCESS is returned. - - If the value pointed to by NamespaceId is the namespace ID of the last namespace on the NVM - Express controller, then EFI_NOT_FOUND is returned. - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express - namespace present on the NVM Express controller. On output, a - pointer to the next NamespaceId of an NVM Express namespace on - an NVM Express controller. An input value of 0xFFFFFFFF retrieves - the first NamespaceId for an NVM Express namespace present on an - NVM Express controller. - - @retval EFI_SUCCESS The Namespace ID of the next Namespace was returned. - @retval EFI_NOT_FOUND There are no more namespaces defined on this controller. - @retval EFI_INVALID_PARAMETER NamespaceId is an invalid value other than 0xFFFFFFFF. - -**/ -EFI_STATUS -EFIAPI -NvmExpressGetNextNamespace ( - IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, - IN OUT UINT32 *NamespaceId - ); - -/** - Used to translate a device path node to a namespace ID. - - The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamespace() function determines the namespace ID associated with the - namespace described by DevicePath. - - If DevicePath is a device path node type that the NVM Express Pass Thru driver supports, then the NVM Express - Pass Thru driver will attempt to translate the contents DevicePath into a namespace ID. - - If this translation is successful, then that namespace ID is returned in NamespaceId, and EFI_SUCCESS is returned - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on - the NVM Express controller. - @param[out] NamespaceId The NVM Express namespace ID contained in the device path node. - - @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId. - @retval EFI_INVALID_PARAMETER If DevicePath or NamespaceId are NULL, then EFI_INVALID_PARAMETER is returned. - @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver - supports, then EFI_UNSUPPORTED is returned. - @retval EFI_NOT_FOUND If DevicePath is a device path node type that the NVM Express Pass Thru driver - supports, but there is not a valid translation from DevicePath to a namespace ID, - then EFI_NOT_FOUND is returned. -**/ -EFI_STATUS -EFIAPI -NvmExpressGetNamespace ( - IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT UINT32 *NamespaceId - ); - -/** - Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller. - - The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device - path node for the NVM Express namespace specified by NamespaceId. - - If the NamespaceId is not valid, then EFI_NOT_FOUND is returned. - - If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. - - If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned. - - Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are - initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned. - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @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,out] DevicePath A pointer to a single device path node that describes the NVM Express - namespace specified by NamespaceId. This function is responsible for - allocating the buffer DevicePath with the boot service AllocatePool(). - It is the caller's responsibility to free DevicePath when the caller - is finished with DevicePath. - @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified - by NamespaceId was allocated and returned in DevicePath. - @retval EFI_NOT_FOUND The NamespaceId is not valid. - @retval EFI_INVALID_PARAMETER DevicePath is NULL. - @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node. - -**/ -EFI_STATUS -EFIAPI -NvmExpressBuildDevicePath ( - IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, - IN UINT32 NamespaceId, - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ); - -/** - Dump the execution status from a given completion queue entry. - - @param[in] Cq A pointer to the NVME_CQ item. - -**/ -VOID -NvmeDumpStatus ( - IN NVME_CQ *Cq - ); - -/** - Register the shutdown notification through the ResetNotification protocol. - - Register the shutdown notification when mNvmeControllerNumber increased from 0 to 1. -**/ -VOID -NvmeRegisterShutdownNotification ( - VOID - ); - -/** - Unregister the shutdown notification through the ResetNotification protocol. - - Unregister the shutdown notification when mNvmeControllerNumber decreased from 1 to 0. -**/ -VOID -NvmeUnregisterShutdownNotification ( - VOID - ); - -#endif diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.c b/MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.c deleted file mode 100644 index 5d0ae3056..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.c +++ /dev/null @@ -1,1889 +0,0 @@ -/** @file - NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows - NVM Express specification. - - Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "NvmExpress.h" - -/** - Read some sectors from the device. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure. - @param Buffer The buffer used to store the data read from the device. - @param Lba The start block number. - @param Blocks Total block number to be read. - - @retval EFI_SUCCESS Datum are read from the device. - @retval Others Fail to read all the datum. - -**/ -EFI_STATUS -ReadSectors ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - IN UINT64 Buffer, - IN UINT64 Lba, - IN UINT32 Blocks - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - UINT32 Bytes; - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - UINT32 BlockSize; - - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - Bytes = Blocks * BlockSize; - - 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; - - CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC; - CommandPacket.NvmeCmd->Nsid = Device->NamespaceId; - CommandPacket.TransferBuffer = (VOID *)(UINTN)Buffer; - - CommandPacket.TransferLength = Bytes; - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket.QueueType = NVME_IO_QUEUE; - - CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba; - CommandPacket.NvmeCmd->Cdw11 = (UINT32)RShiftU64 (Lba, 32); - CommandPacket.NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF; - - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - Device->NamespaceId, - &CommandPacket, - NULL - ); - - return Status; -} - -/** - Write some sectors to the device. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure. - @param Buffer The buffer to be written into the device. - @param Lba The start block number. - @param Blocks Total block number to be written. - - @retval EFI_SUCCESS Datum are written into the buffer. - @retval Others Fail to write all the datum. - -**/ -EFI_STATUS -WriteSectors ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - IN UINT64 Buffer, - IN UINT64 Lba, - IN UINT32 Blocks - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - UINT32 Bytes; - UINT32 BlockSize; - - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - Bytes = Blocks * BlockSize; - - 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; - - CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC; - CommandPacket.NvmeCmd->Nsid = Device->NamespaceId; - CommandPacket.TransferBuffer = (VOID *)(UINTN)Buffer; - - CommandPacket.TransferLength = Bytes; - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket.QueueType = NVME_IO_QUEUE; - - CommandPacket.NvmeCmd->Cdw10 = (UINT32)Lba; - CommandPacket.NvmeCmd->Cdw11 = (UINT32)RShiftU64 (Lba, 32); - // - // Set Force Unit Access bit (bit 30) to use write-through behaviour - // - CommandPacket.NvmeCmd->Cdw12 = ((Blocks - 1) & 0xFFFF) | BIT30; - - CommandPacket.MetadataBuffer = NULL; - CommandPacket.MetadataLength = 0; - - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - Device->NamespaceId, - &CommandPacket, - NULL - ); - - return Status; -} - -/** - Read some blocks from the device. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure. - @param Buffer The buffer used to store the data read from the device. - @param Lba The start block number. - @param Blocks Total block number to be read. - - @retval EFI_SUCCESS Datum are read from the device. - @retval Others Fail to read all the datum. - -**/ -EFI_STATUS -NvmeRead ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - OUT VOID *Buffer, - IN UINT64 Lba, - IN UINTN Blocks - ) -{ - EFI_STATUS Status; - UINT32 BlockSize; - NVME_CONTROLLER_PRIVATE_DATA *Private; - UINT32 MaxTransferBlocks; - UINTN OrginalBlocks; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - - // - // Wait for the device's asynchronous I/O queue to become empty. - // - while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&Device->AsyncQueue); - gBS->RestoreTPL (OldTpl); - - if (IsEmpty) { - break; - } - - gBS->Stall (100); - } - - Status = EFI_SUCCESS; - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - OrginalBlocks = Blocks; - - if (Private->ControllerData->Mdts != 0) { - MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize; - } else { - MaxTransferBlocks = 1024; - } - - while (Blocks > 0) { - if (Blocks > MaxTransferBlocks) { - Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks); - - Blocks -= MaxTransferBlocks; - Buffer = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize); - Lba += MaxTransferBlocks; - } else { - Status = ReadSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks); - Blocks = 0; - } - - if (EFI_ERROR (Status)) { - break; - } - } - - DEBUG (( - DEBUG_BLKIO, - "%a: Lba = 0x%08Lx, Original = 0x%08Lx, " - "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", - __func__, - Lba, - (UINT64)OrginalBlocks, - (UINT64)Blocks, - BlockSize, - Status - )); - - return Status; -} - -/** - Write some blocks to the device. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure. - @param Buffer The buffer to be written into the device. - @param Lba The start block number. - @param Blocks Total block number to be written. - - @retval EFI_SUCCESS Datum are written into the buffer. - @retval Others Fail to write all the datum. - -**/ -EFI_STATUS -NvmeWrite ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - IN VOID *Buffer, - IN UINT64 Lba, - IN UINTN Blocks - ) -{ - EFI_STATUS Status; - UINT32 BlockSize; - NVME_CONTROLLER_PRIVATE_DATA *Private; - UINT32 MaxTransferBlocks; - UINTN OrginalBlocks; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - - // - // Wait for the device's asynchronous I/O queue to become empty. - // - while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&Device->AsyncQueue); - gBS->RestoreTPL (OldTpl); - - if (IsEmpty) { - break; - } - - gBS->Stall (100); - } - - Status = EFI_SUCCESS; - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - OrginalBlocks = Blocks; - - if (Private->ControllerData->Mdts != 0) { - MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize; - } else { - MaxTransferBlocks = 1024; - } - - while (Blocks > 0) { - if (Blocks > MaxTransferBlocks) { - Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, MaxTransferBlocks); - - Blocks -= MaxTransferBlocks; - Buffer = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize); - Lba += MaxTransferBlocks; - } else { - Status = WriteSectors (Device, (UINT64)(UINTN)Buffer, Lba, (UINT32)Blocks); - Blocks = 0; - } - - if (EFI_ERROR (Status)) { - break; - } - } - - DEBUG (( - DEBUG_BLKIO, - "%a: Lba = 0x%08Lx, Original = 0x%08Lx, " - "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", - __func__, - Lba, - (UINT64)OrginalBlocks, - (UINT64)Blocks, - BlockSize, - Status - )); - - return Status; -} - -/** - Flushes all modified data to the device. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS Datum are written into the buffer. - @retval Others Fail to write all the datum. - -**/ -EFI_STATUS -NvmeFlush ( - IN NVME_DEVICE_PRIVATE_DATA *Device - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - - Private = Device->Controller; - - 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; - - CommandPacket.NvmeCmd->Cdw0.Opcode = NVME_IO_FLUSH_OPC; - CommandPacket.NvmeCmd->Nsid = Device->NamespaceId; - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket.QueueType = NVME_IO_QUEUE; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - Device->NamespaceId, - &CommandPacket, - NULL - ); - - return Status; -} - -/** - Nonblocking I/O callback funtion when the event is signaled. - - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registered to the - Event. - -**/ -VOID -EFIAPI -AsyncIoCallback ( - IN EFI_EVENT Event, - IN VOID *Context - ) -{ - NVME_BLKIO2_SUBTASK *Subtask; - NVME_BLKIO2_REQUEST *Request; - NVME_CQ *Completion; - EFI_BLOCK_IO2_TOKEN *Token; - - gBS->CloseEvent (Event); - - Subtask = (NVME_BLKIO2_SUBTASK *)Context; - Completion = (NVME_CQ *)Subtask->CommandPacket->NvmeCompletion; - Request = Subtask->BlockIo2Request; - Token = Request->Token; - - if (Token->TransactionStatus == EFI_SUCCESS) { - // - // If previous subtask already fails, do not check the result of - // subsequent subtasks. - // - if ((Completion->Sct != 0) || (Completion->Sc != 0)) { - Token->TransactionStatus = EFI_DEVICE_ERROR; - - // - // Dump completion entry status for debugging. - // - DEBUG_CODE_BEGIN (); - NvmeDumpStatus (Completion); - DEBUG_CODE_END (); - } - } - - // - // Remove the subtask from the BlockIo2 subtasks list. - // - RemoveEntryList (&Subtask->Link); - - if (IsListEmpty (&Request->SubtasksQueue) && Request->LastSubtaskSubmitted) { - // - // Remove the BlockIo2 request from the device asynchronous queue. - // - RemoveEntryList (&Request->Link); - FreePool (Request); - gBS->SignalEvent (Token->Event); - } - - FreePool (Subtask->CommandPacket->NvmeCmd); - FreePool (Subtask->CommandPacket->NvmeCompletion); - FreePool (Subtask->CommandPacket); - FreePool (Subtask); -} - -/** - Read some sectors from the device in an asynchronous manner. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data - structure. - @param Request The pointer to the NVME_BLKIO2_REQUEST data structure. - @param Buffer The buffer used to store the data read from the device. - @param Lba The start block number. - @param Blocks Total block number to be read. - @param IsLast The last subtask of an asynchronous read request. - - @retval EFI_SUCCESS Asynchronous read request has been queued. - @retval Others Fail to send the asynchronous request. - -**/ -EFI_STATUS -AsyncReadSectors ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - IN NVME_BLKIO2_REQUEST *Request, - IN UINT64 Buffer, - IN UINT64 Lba, - IN UINT32 Blocks, - IN BOOLEAN IsLast - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - UINT32 Bytes; - NVME_BLKIO2_SUBTASK *Subtask; - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *CommandPacket; - EFI_NVM_EXPRESS_COMMAND *Command; - EFI_NVM_EXPRESS_COMPLETION *Completion; - EFI_STATUS Status; - UINT32 BlockSize; - EFI_TPL OldTpl; - - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - Bytes = Blocks * BlockSize; - CommandPacket = NULL; - Command = NULL; - Completion = NULL; - - Subtask = AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK)); - if (Subtask == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - Subtask->Signature = NVME_BLKIO2_SUBTASK_SIGNATURE; - Subtask->IsLast = IsLast; - Subtask->NamespaceId = Device->NamespaceId; - Subtask->BlockIo2Request = Request; - - CommandPacket = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - if (CommandPacket == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } else { - Subtask->CommandPacket = CommandPacket; - } - - Command = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND)); - if (Command == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - Completion = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION)); - if (Completion == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - // - // Create Event - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - AsyncIoCallback, - Subtask, - &Subtask->Event - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - CommandPacket->NvmeCmd = Command; - CommandPacket->NvmeCompletion = Completion; - - CommandPacket->NvmeCmd->Cdw0.Opcode = NVME_IO_READ_OPC; - CommandPacket->NvmeCmd->Nsid = Device->NamespaceId; - CommandPacket->TransferBuffer = (VOID *)(UINTN)Buffer; - - CommandPacket->TransferLength = Bytes; - CommandPacket->CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket->QueueType = NVME_IO_QUEUE; - - CommandPacket->NvmeCmd->Cdw10 = (UINT32)Lba; - CommandPacket->NvmeCmd->Cdw11 = (UINT32)RShiftU64 (Lba, 32); - CommandPacket->NvmeCmd->Cdw12 = (Blocks - 1) & 0xFFFF; - - CommandPacket->NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID; - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - InsertTailList (&Private->UnsubmittedSubtasks, &Subtask->Link); - Request->UnsubmittedSubtaskNum++; - gBS->RestoreTPL (OldTpl); - - return EFI_SUCCESS; - -ErrorExit: - // - // Resource cleanup if asynchronous read request has not been queued. - // - if (Completion != NULL) { - FreePool (Completion); - } - - if (Command != NULL) { - FreePool (Command); - } - - if (CommandPacket != NULL) { - FreePool (CommandPacket); - } - - if (Subtask != NULL) { - if (Subtask->Event != NULL) { - gBS->CloseEvent (Subtask->Event); - } - - FreePool (Subtask); - } - - return Status; -} - -/** - Write some sectors from the device in an asynchronous manner. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data - structure. - @param Request The pointer to the NVME_BLKIO2_REQUEST data structure. - @param Buffer The buffer used to store the data written to the - device. - @param Lba The start block number. - @param Blocks Total block number to be written. - @param IsLast The last subtask of an asynchronous write request. - - @retval EFI_SUCCESS Asynchronous write request has been queued. - @retval Others Fail to send the asynchronous request. - -**/ -EFI_STATUS -AsyncWriteSectors ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - IN NVME_BLKIO2_REQUEST *Request, - IN UINT64 Buffer, - IN UINT64 Lba, - IN UINT32 Blocks, - IN BOOLEAN IsLast - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - UINT32 Bytes; - NVME_BLKIO2_SUBTASK *Subtask; - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET *CommandPacket; - EFI_NVM_EXPRESS_COMMAND *Command; - EFI_NVM_EXPRESS_COMPLETION *Completion; - EFI_STATUS Status; - UINT32 BlockSize; - EFI_TPL OldTpl; - - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - Bytes = Blocks * BlockSize; - CommandPacket = NULL; - Command = NULL; - Completion = NULL; - - Subtask = AllocateZeroPool (sizeof (NVME_BLKIO2_SUBTASK)); - if (Subtask == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - Subtask->Signature = NVME_BLKIO2_SUBTASK_SIGNATURE; - Subtask->IsLast = IsLast; - Subtask->NamespaceId = Device->NamespaceId; - Subtask->BlockIo2Request = Request; - - CommandPacket = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - if (CommandPacket == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } else { - Subtask->CommandPacket = CommandPacket; - } - - Command = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMMAND)); - if (Command == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - Completion = AllocateZeroPool (sizeof (EFI_NVM_EXPRESS_COMPLETION)); - if (Completion == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ErrorExit; - } - - // - // Create Event - // - Status = gBS->CreateEvent ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - AsyncIoCallback, - Subtask, - &Subtask->Event - ); - if (EFI_ERROR (Status)) { - goto ErrorExit; - } - - CommandPacket->NvmeCmd = Command; - CommandPacket->NvmeCompletion = Completion; - - CommandPacket->NvmeCmd->Cdw0.Opcode = NVME_IO_WRITE_OPC; - CommandPacket->NvmeCmd->Nsid = Device->NamespaceId; - CommandPacket->TransferBuffer = (VOID *)(UINTN)Buffer; - - CommandPacket->TransferLength = Bytes; - CommandPacket->CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket->QueueType = NVME_IO_QUEUE; - - CommandPacket->NvmeCmd->Cdw10 = (UINT32)Lba; - CommandPacket->NvmeCmd->Cdw11 = (UINT32)RShiftU64 (Lba, 32); - // - // Set Force Unit Access bit (bit 30) to use write-through behaviour - // - CommandPacket->NvmeCmd->Cdw12 = ((Blocks - 1) & 0xFFFF) | BIT30; - - CommandPacket->NvmeCmd->Flags = CDW10_VALID | CDW11_VALID | CDW12_VALID; - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - InsertTailList (&Private->UnsubmittedSubtasks, &Subtask->Link); - Request->UnsubmittedSubtaskNum++; - gBS->RestoreTPL (OldTpl); - - return EFI_SUCCESS; - -ErrorExit: - // - // Resource cleanup if asynchronous read request has not been queued. - // - if (Completion != NULL) { - FreePool (Completion); - } - - if (Command != NULL) { - FreePool (Command); - } - - if (CommandPacket != NULL) { - FreePool (CommandPacket); - } - - if (Subtask != NULL) { - if (Subtask->Event != NULL) { - gBS->CloseEvent (Subtask->Event); - } - - FreePool (Subtask); - } - - return Status; -} - -/** - Read some blocks from the device in an asynchronous manner. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data - structure. - @param Buffer The buffer used to store the data read from the device. - @param Lba The start block number. - @param Blocks Total block number to be read. - @param Token A pointer to the token associated with the transaction. - - @retval EFI_SUCCESS Data are read from the device. - @retval Others Fail to read all the data. - -**/ -EFI_STATUS -NvmeAsyncRead ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - OUT VOID *Buffer, - IN UINT64 Lba, - IN UINTN Blocks, - IN EFI_BLOCK_IO2_TOKEN *Token - ) -{ - EFI_STATUS Status; - UINT32 BlockSize; - NVME_CONTROLLER_PRIVATE_DATA *Private; - NVME_BLKIO2_REQUEST *BlkIo2Req; - UINT32 MaxTransferBlocks; - UINTN OrginalBlocks; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - - Status = EFI_SUCCESS; - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - OrginalBlocks = Blocks; - BlkIo2Req = AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST)); - if (BlkIo2Req == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - BlkIo2Req->Signature = NVME_BLKIO2_REQUEST_SIGNATURE; - BlkIo2Req->Token = Token; - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - InsertTailList (&Device->AsyncQueue, &BlkIo2Req->Link); - gBS->RestoreTPL (OldTpl); - - InitializeListHead (&BlkIo2Req->SubtasksQueue); - - if (Private->ControllerData->Mdts != 0) { - MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize; - } else { - MaxTransferBlocks = 1024; - } - - while (Blocks > 0) { - if (Blocks > MaxTransferBlocks) { - Status = AsyncReadSectors ( - Device, - BlkIo2Req, - (UINT64)(UINTN)Buffer, - Lba, - MaxTransferBlocks, - FALSE - ); - - Blocks -= MaxTransferBlocks; - Buffer = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize); - Lba += MaxTransferBlocks; - } else { - Status = AsyncReadSectors ( - Device, - BlkIo2Req, - (UINT64)(UINTN)Buffer, - Lba, - (UINT32)Blocks, - TRUE - ); - - Blocks = 0; - } - - if (EFI_ERROR (Status)) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&BlkIo2Req->SubtasksQueue) && - (BlkIo2Req->UnsubmittedSubtaskNum == 0); - - if (IsEmpty) { - // - // Remove the BlockIo2 request from the device asynchronous queue. - // - RemoveEntryList (&BlkIo2Req->Link); - FreePool (BlkIo2Req); - Status = EFI_DEVICE_ERROR; - } else { - // - // There are previous BlockIo2 subtasks still running, EFI_SUCCESS - // should be returned to make sure that the caller does not free - // resources still using by these requests. - // - Status = EFI_SUCCESS; - Token->TransactionStatus = EFI_DEVICE_ERROR; - BlkIo2Req->LastSubtaskSubmitted = TRUE; - } - - gBS->RestoreTPL (OldTpl); - - break; - } - } - - DEBUG (( - DEBUG_BLKIO, - "%a: Lba = 0x%08Lx, Original = 0x%08Lx, " - "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", - __func__, - Lba, - (UINT64)OrginalBlocks, - (UINT64)Blocks, - BlockSize, - Status - )); - - return Status; -} - -/** - Write some blocks from the device in an asynchronous manner. - - @param Device The pointer to the NVME_DEVICE_PRIVATE_DATA data - structure. - @param Buffer The buffer used to store the data written to the - device. - @param Lba The start block number. - @param Blocks Total block number to be written. - @param Token A pointer to the token associated with the transaction. - - @retval EFI_SUCCESS Data are written to the device. - @retval Others Fail to write all the data. - -**/ -EFI_STATUS -NvmeAsyncWrite ( - IN NVME_DEVICE_PRIVATE_DATA *Device, - IN VOID *Buffer, - IN UINT64 Lba, - IN UINTN Blocks, - IN EFI_BLOCK_IO2_TOKEN *Token - ) -{ - EFI_STATUS Status; - UINT32 BlockSize; - NVME_CONTROLLER_PRIVATE_DATA *Private; - NVME_BLKIO2_REQUEST *BlkIo2Req; - UINT32 MaxTransferBlocks; - UINTN OrginalBlocks; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - - Status = EFI_SUCCESS; - Private = Device->Controller; - BlockSize = Device->Media.BlockSize; - OrginalBlocks = Blocks; - BlkIo2Req = AllocateZeroPool (sizeof (NVME_BLKIO2_REQUEST)); - if (BlkIo2Req == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - BlkIo2Req->Signature = NVME_BLKIO2_REQUEST_SIGNATURE; - BlkIo2Req->Token = Token; - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - InsertTailList (&Device->AsyncQueue, &BlkIo2Req->Link); - gBS->RestoreTPL (OldTpl); - - InitializeListHead (&BlkIo2Req->SubtasksQueue); - - if (Private->ControllerData->Mdts != 0) { - MaxTransferBlocks = (1 << (Private->ControllerData->Mdts)) * (1 << (Private->Cap.Mpsmin + 12)) / BlockSize; - } else { - MaxTransferBlocks = 1024; - } - - while (Blocks > 0) { - if (Blocks > MaxTransferBlocks) { - Status = AsyncWriteSectors ( - Device, - BlkIo2Req, - (UINT64)(UINTN)Buffer, - Lba, - MaxTransferBlocks, - FALSE - ); - - Blocks -= MaxTransferBlocks; - Buffer = (VOID *)(UINTN)((UINT64)(UINTN)Buffer + MaxTransferBlocks * BlockSize); - Lba += MaxTransferBlocks; - } else { - Status = AsyncWriteSectors ( - Device, - BlkIo2Req, - (UINT64)(UINTN)Buffer, - Lba, - (UINT32)Blocks, - TRUE - ); - - Blocks = 0; - } - - if (EFI_ERROR (Status)) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&BlkIo2Req->SubtasksQueue) && - (BlkIo2Req->UnsubmittedSubtaskNum == 0); - - if (IsEmpty) { - // - // Remove the BlockIo2 request from the device asynchronous queue. - // - RemoveEntryList (&BlkIo2Req->Link); - FreePool (BlkIo2Req); - Status = EFI_DEVICE_ERROR; - } else { - // - // There are previous BlockIo2 subtasks still running, EFI_SUCCESS - // should be returned to make sure that the caller does not free - // resources still using by these requests. - // - Status = EFI_SUCCESS; - Token->TransactionStatus = EFI_DEVICE_ERROR; - BlkIo2Req->LastSubtaskSubmitted = TRUE; - } - - gBS->RestoreTPL (OldTpl); - - break; - } - } - - DEBUG (( - DEBUG_BLKIO, - "%a: Lba = 0x%08Lx, Original = 0x%08Lx, " - "Remaining = 0x%08Lx, BlockSize = 0x%x, Status = %r\n", - __func__, - Lba, - (UINT64)OrginalBlocks, - (UINT64)Blocks, - BlockSize, - Status - )); - - return Status; -} - -/** - Reset the Block Device. - - @param This Indicates a pointer to the calling context. - @param ExtendedVerification Driver may perform diagnostics on reset. - - @retval EFI_SUCCESS The device was reset. - @retval EFI_DEVICE_ERROR The device is not functioning properly and could - not be reset. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_TPL OldTpl; - NVME_CONTROLLER_PRIVATE_DATA *Private; - NVME_DEVICE_PRIVATE_DATA *Device; - EFI_STATUS Status; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // For Nvm Express subsystem, reset block device means reset controller. - // - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This); - - Private = Device->Controller; - - Status = NvmeControllerReset (Private); // MU_CHANGE - Allocate IO Queue Buffer - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - } - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Read BufferSize bytes from Lba into Buffer. - - @param This Indicates a pointer to the calling context. - @param MediaId Id of the media, changes every time the media is replaced. - @param Lba The starting Logical Block Address to read from. - @param BufferSize Size of Buffer, must be a multiple of device block size. - @param Buffer A pointer to the destination buffer for the data. The caller is - responsible for either having implicit or explicit ownership of the buffer. - - @retval EFI_SUCCESS The data was read correctly from the device. - @retval EFI_DEVICE_ERROR The device reported an error while performing the read. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. - @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, - or the buffer is not on proper alignment. - -**/ -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; - EFI_TPL OldTpl; - - // - // 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; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This); - - Status = NvmeRead (Device, Buffer, Lba, NumberOfBlocks); - - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - Write BufferSize bytes from Lba into Buffer. - - @param This Indicates a pointer to the calling context. - @param MediaId The media ID that the write request is for. - @param Lba The starting logical block address to be written. The caller is - responsible for writing to only legitimate locations. - @param BufferSize Size of Buffer, must be a multiple of device block size. - @param Buffer A pointer to the source buffer for the data. - - @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_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the 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 -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; - EFI_TPL OldTpl; - - // - // 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; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This); - - Status = NvmeWrite (Device, Buffer, Lba, NumberOfBlocks); - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Flush the Block Device. - - @param This Indicates a pointer to the calling context. - - @retval EFI_SUCCESS All outstanding data was written to the device. - @retval EFI_DEVICE_ERROR The device reported an error while writing back the data. - @retval EFI_NO_MEDIA There is no media in the device. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ) -{ - NVME_DEVICE_PRIVATE_DATA *Device; - EFI_STATUS Status; - EFI_TPL OldTpl; - - // - // Check parameters. - // - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO (This); - - Status = NvmeFlush (Device); - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Reset the block device hardware. - - @param[in] This Indicates a pointer to the calling context. - @param[in] ExtendedVerification Indicates that the driver may perform a more - exhausive verfication operation of the - device during reset. - - @retval EFI_SUCCESS The device was reset. - @retval EFI_DEVICE_ERROR The device is not functioning properly and could - not be reset. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoResetEx ( - IN EFI_BLOCK_IO2_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ) -{ - EFI_STATUS Status; - NVME_DEVICE_PRIVATE_DATA *Device; - NVME_CONTROLLER_PRIVATE_DATA *Private; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This); - Private = Device->Controller; - - // - // Wait for the asynchronous PassThru queue to become empty. - // - while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&Private->AsyncPassThruQueue) && - IsListEmpty (&Private->UnsubmittedSubtasks); - gBS->RestoreTPL (OldTpl); - - if (IsEmpty) { - break; - } - - gBS->Stall (100); - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Status = NvmeControllerReset (Private); // MU_CHANGE - Allocate IO Queue Buffer - - if (EFI_ERROR (Status)) { - Status = EFI_DEVICE_ERROR; - } - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Read BufferSize bytes from Lba into Buffer. - - This function reads the requested number of blocks from the device. All the - blocks are read, or an error is returned. - If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and - non-blocking I/O is being used, the Event associated with this request will - not be signaled. - - @param[in] This Indicates a pointer to the calling context. - @param[in] MediaId Id of the media, changes every time the media is - replaced. - @param[in] Lba The starting Logical Block Address to read from. - @param[in, out] Token A pointer to the token associated with the - transaction. - @param[in] BufferSize Size of Buffer, must be a multiple of device - block size. - @param[out] Buffer A pointer to the destination buffer for the data. - The caller is responsible for either having - implicit or explicit ownership of the buffer. - - @retval EFI_SUCCESS The read request was queued if Token->Event is - not NULL.The data was read correctly from the - device if the Token->Event is NULL. - @retval EFI_DEVICE_ERROR The device reported an error while performing - the read. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of - the intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not - valid, or the buffer is not on proper - alignment. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a - lack of resources. - -**/ -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_STATUS Status; - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - UINTN IoAlign; - EFI_TPL OldTpl; - - // - // 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) { - if ((Token != NULL) && (Token->Event != NULL)) { - Token->TransactionStatus = EFI_SUCCESS; - gBS->SignalEvent (Token->Event); - } - - 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; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This); - - if ((Token != NULL) && (Token->Event != NULL)) { - Token->TransactionStatus = EFI_SUCCESS; - Status = NvmeAsyncRead (Device, Buffer, Lba, NumberOfBlocks, Token); - } else { - Status = NvmeRead (Device, Buffer, Lba, NumberOfBlocks); - } - - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - Write BufferSize bytes from Lba into Buffer. - - This function writes the requested number of blocks to the device. All blocks - are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA, - EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is - being used, the Event associated with this request will not be signaled. - - @param[in] This Indicates a pointer to the calling context. - @param[in] MediaId The media ID that the write request is for. - @param[in] Lba The starting logical block address to be written. - The caller is responsible for writing to only - legitimate locations. - @param[in, out] Token A pointer to the token associated with the - transaction. - @param[in] BufferSize Size of Buffer, must be a multiple of device - block size. - @param[in] Buffer A pointer to the source buffer for the data. - - @retval EFI_SUCCESS The write request was queued if Event is not - NULL. - The data was written correctly to the device if - the Event is NULL. - @retval EFI_WRITE_PROTECTED The device can not be written to. - @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_DEVICE_ERROR The device reported an error while performing - the write. - @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size - of the device. - @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not - valid, or the buffer is not on proper - alignment. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a - lack of resources. - -**/ -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_STATUS Status; - EFI_BLOCK_IO_MEDIA *Media; - UINTN BlockSize; - UINTN NumberOfBlocks; - UINTN IoAlign; - EFI_TPL OldTpl; - - // - // 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) { - if ((Token != NULL) && (Token->Event != NULL)) { - Token->TransactionStatus = EFI_SUCCESS; - gBS->SignalEvent (Token->Event); - } - - 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; - } - - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This); - - if ((Token != NULL) && (Token->Event != NULL)) { - Token->TransactionStatus = EFI_SUCCESS; - Status = NvmeAsyncWrite (Device, Buffer, Lba, NumberOfBlocks, Token); - } else { - Status = NvmeWrite (Device, Buffer, Lba, NumberOfBlocks); - } - - gBS->RestoreTPL (OldTpl); - return Status; -} - -/** - Flush the Block Device. - - If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED - is returned and non-blocking I/O is being used, the Event associated with - this request will not be signaled. - - @param[in] This Indicates a pointer to the calling context. - @param[in,out] Token A pointer to the token associated with the - transaction. - - @retval EFI_SUCCESS The flush request was queued if Event is not - NULL. - All outstanding data was written correctly to - the device if the Event is NULL. - @retval EFI_DEVICE_ERROR The device reported an error while writting back - the data. - @retval EFI_WRITE_PROTECTED The device cannot be written to. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack - of resources. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoFlushBlocksEx ( - IN EFI_BLOCK_IO2_PROTOCOL *This, - IN OUT EFI_BLOCK_IO2_TOKEN *Token - ) -{ - NVME_DEVICE_PRIVATE_DATA *Device; - BOOLEAN IsEmpty; - EFI_TPL OldTpl; - - // - // Check parameters. - // - if (This == NULL) { - return EFI_INVALID_PARAMETER; - } - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_BLOCK_IO2 (This); - - // - // Wait for the asynchronous I/O queue to become empty. - // - while (TRUE) { - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - IsEmpty = IsListEmpty (&Device->AsyncQueue); - gBS->RestoreTPL (OldTpl); - - if (IsEmpty) { - break; - } - - gBS->Stall (100); - } - - // - // Signal caller event - // - if ((Token != NULL) && (Token->Event != NULL)) { - Token->TransactionStatus = EFI_SUCCESS; - gBS->SignalEvent (Token->Event); - } - - return EFI_SUCCESS; -} - -/** - Trust transfer data from/to NVMe device. - - This function performs one NVMe transaction to do a trust transfer from/to NVMe device. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Buffer The pointer to the current transaction buffer. - @param SecurityProtocolId The value of the "Security Protocol" parameter of - the security protocol command to be sent. - @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter - of the security protocol command to be sent. - @param TransferLength The block number or sector count of the transfer. - @param IsTrustSend Indicates whether it is a trust send operation or not. - @param Timeout The timeout, in 100ns units, to use for the execution - of the security protocol command. A Timeout value of 0 - means that this function will wait indefinitely for the - security protocol command to execute. If Timeout is greater - than zero, then this function will return EFI_TIMEOUT - if the time required to execute the receive data command - is greater than Timeout. - @param TransferLengthOut A pointer to a buffer to store the size in bytes of the data - written to the buffer. Ignore it when IsTrustSend is TRUE. - - @retval EFI_SUCCESS The data transfer is complete successfully. - @return others Some error occurs when transferring data. - -**/ -EFI_STATUS -TrustTransferNvmeDevice ( - IN OUT NVME_CONTROLLER_PRIVATE_DATA *Private, - IN OUT VOID *Buffer, - IN UINT8 SecurityProtocolId, - IN UINT16 SecurityProtocolSpecificData, - IN UINTN TransferLength, - IN BOOLEAN IsTrustSend, - IN UINT64 Timeout, - OUT UINTN *TransferLengthOut - ) -{ - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - UINT16 SpecificData; - - 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; - - // - // Change Endianness of SecurityProtocolSpecificData - // - SpecificData = (((SecurityProtocolSpecificData << 8) & 0xFF00) | (SecurityProtocolSpecificData >> 8)); - - if (IsTrustSend) { - Command.Cdw0.Opcode = NVME_ADMIN_SECURITY_SEND_CMD; - CommandPacket.TransferBuffer = Buffer; - CommandPacket.TransferLength = (UINT32)TransferLength; - CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) | (SpecificData << 8)); - CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength; - } else { - Command.Cdw0.Opcode = NVME_ADMIN_SECURITY_RECEIVE_CMD; - CommandPacket.TransferBuffer = Buffer; - CommandPacket.TransferLength = (UINT32)TransferLength; - CommandPacket.NvmeCmd->Cdw10 = (UINT32)((SecurityProtocolId << 24) | (SpecificData << 8)); - CommandPacket.NvmeCmd->Cdw11 = (UINT32)TransferLength; - } - - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID; - CommandPacket.NvmeCmd->Nsid = NVME_CONTROLLER_ID; - CommandPacket.CommandTimeout = Timeout; - CommandPacket.QueueType = NVME_ADMIN_QUEUE; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - NVME_CONTROLLER_ID, - &CommandPacket, - NULL - ); - - if (!IsTrustSend) { - if (EFI_ERROR (Status)) { - *TransferLengthOut = 0; - } else { - *TransferLengthOut = (UINTN)TransferLength; - } - } - - return Status; -} - -/** - Send a security protocol command to a device that receives data and/or the result - of one or more commands sent by SendData. - - The ReceiveData function sends a security protocol command to the given MediaId. - The security protocol command sent is defined by SecurityProtocolId and contains - the security protocol specific data SecurityProtocolSpecificData. The function - returns the data from the security protocol command in PayloadBuffer. - - For devices supporting the SCSI command set, the security protocol command is sent - using the SECURITY PROTOCOL IN command defined in SPC-4. - - For devices supporting the ATA command set, the security protocol command is sent - using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize - is non-zero. - - If the PayloadBufferSize is zero, the security protocol command is sent using the - Trusted Non-Data command defined in ATA8-ACS. - - If PayloadBufferSize is too small to store the available data from the security - protocol command, the function shall copy PayloadBufferSize bytes into the - PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL. - - If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero, - the function shall return EFI_INVALID_PARAMETER. - - If the given MediaId does not support security protocol commands, the function shall - return EFI_UNSUPPORTED. If there is no media in the device, the function returns - EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device, - the function returns EFI_MEDIA_CHANGED. - - If the security protocol fails to complete within the Timeout period, the function - shall return EFI_TIMEOUT. - - If the security protocol command completes without an error, the function shall - return EFI_SUCCESS. If the security protocol command completes with an error, the - function shall return EFI_DEVICE_ERROR. - - @param This Indicates a pointer to the calling context. - @param MediaId ID of the medium to receive data from. If there is no - block IO protocol supported by the physical device, the - value of MediaId is undefined. - @param Timeout The timeout, in 100ns units, to use for the execution - of the security protocol command. A Timeout value of 0 - means that this function will wait indefinitely for the - security protocol command to execute. If Timeout is greater - than zero, then this function will return EFI_TIMEOUT - if the time required to execute the receive data command - is greater than Timeout. - @param SecurityProtocolId The value of the "Security Protocol" parameter of - the security protocol command to be sent. - @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter - of the security protocol command to be sent. - @param PayloadBufferSize Size in bytes of the payload data buffer. - @param PayloadBuffer A pointer to a destination buffer to store the security - protocol command specific payload data for the security - protocol command. The caller is responsible for having - either implicit or explicit ownership of the buffer. - @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the - data written to the payload data buffer. - - @retval EFI_SUCCESS The security protocol command completed successfully. - @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available - data from the device. The PayloadBuffer contains the truncated data. - @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands. - @retval EFI_DEVICE_ERROR The security protocol command completed with an error. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and - PayloadBufferSize is non-zero. - @retval EFI_TIMEOUT A timeout occurred while waiting for the security - protocol command to execute. - -**/ -EFI_STATUS -EFIAPI -NvmeStorageSecurityReceiveData ( - IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, - IN UINT32 MediaId, - IN UINT64 Timeout, - IN UINT8 SecurityProtocolId, - IN UINT16 SecurityProtocolSpecificData, - IN UINTN PayloadBufferSize, - OUT VOID *PayloadBuffer, - OUT UINTN *PayloadTransferSize - ) -{ - EFI_STATUS Status; - NVME_DEVICE_PRIVATE_DATA *Device; - - Status = EFI_SUCCESS; - - if ((PayloadBuffer == NULL) || (PayloadTransferSize == NULL) || (PayloadBufferSize == 0)) { - return EFI_INVALID_PARAMETER; - } - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This); - - if (MediaId != Device->BlockIo.Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (!Device->BlockIo.Media->MediaPresent) { - return EFI_NO_MEDIA; - } - - Status = TrustTransferNvmeDevice ( - Device->Controller, - PayloadBuffer, - SecurityProtocolId, - SecurityProtocolSpecificData, - PayloadBufferSize, - FALSE, - Timeout, - PayloadTransferSize - ); - - return Status; -} - -/** - Send a security protocol command to a device. - - The SendData function sends a security protocol command containing the payload - PayloadBuffer to the given MediaId. The security protocol command sent is - defined by SecurityProtocolId and contains the security protocol specific data - SecurityProtocolSpecificData. If the underlying protocol command requires a - specific padding for the command payload, the SendData function shall add padding - bytes to the command payload to satisfy the padding requirements. - - For devices supporting the SCSI command set, the security protocol command is sent - using the SECURITY PROTOCOL OUT command defined in SPC-4. - - For devices supporting the ATA command set, the security protocol command is sent - using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize - is non-zero. If the PayloadBufferSize is zero, the security protocol command is - sent using the Trusted Non-Data command defined in ATA8-ACS. - - If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall - return EFI_INVALID_PARAMETER. - - If the given MediaId does not support security protocol commands, the function - shall return EFI_UNSUPPORTED. If there is no media in the device, the function - returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the - device, the function returns EFI_MEDIA_CHANGED. - - If the security protocol fails to complete within the Timeout period, the function - shall return EFI_TIMEOUT. - - If the security protocol command completes without an error, the function shall return - EFI_SUCCESS. If the security protocol command completes with an error, the function - shall return EFI_DEVICE_ERROR. - - @param This Indicates a pointer to the calling context. - @param MediaId ID of the medium to receive data from. If there is no - block IO protocol supported by the physical device, the - value of MediaId is undefined. - @param Timeout The timeout, in 100ns units, to use for the execution - of the security protocol command. A Timeout value of 0 - means that this function will wait indefinitely for the - security protocol command to execute. If Timeout is greater - than zero, then this function will return EFI_TIMEOUT - if the time required to execute the send data command - is greater than Timeout. - @param SecurityProtocolId The value of the "Security Protocol" parameter of - the security protocol command to be sent. - @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter - of the security protocol command to be sent. - @param PayloadBufferSize Size in bytes of the payload data buffer. - @param PayloadBuffer A pointer to a destination buffer to store the security - protocol command specific payload data for the security - protocol command. - - @retval EFI_SUCCESS The security protocol command completed successfully. - @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands. - @retval EFI_DEVICE_ERROR The security protocol command completed with an error. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero. - @retval EFI_TIMEOUT A timeout occurred while waiting for the security - protocol command to execute. - -**/ -EFI_STATUS -EFIAPI -NvmeStorageSecuritySendData ( - IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, - IN UINT32 MediaId, - IN UINT64 Timeout, - IN UINT8 SecurityProtocolId, - IN UINT16 SecurityProtocolSpecificData, - IN UINTN PayloadBufferSize, - IN VOID *PayloadBuffer - ) -{ - EFI_STATUS Status; - NVME_DEVICE_PRIVATE_DATA *Device; - - Status = EFI_SUCCESS; - - if ((PayloadBuffer == NULL) && (PayloadBufferSize != 0)) { - return EFI_INVALID_PARAMETER; - } - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_STORAGE_SECURITY (This); - - if (MediaId != Device->BlockIo.Media->MediaId) { - return EFI_MEDIA_CHANGED; - } - - if (!Device->BlockIo.Media->MediaPresent) { - return EFI_NO_MEDIA; - } - - Status = TrustTransferNvmeDevice ( - Device->Controller, - PayloadBuffer, - SecurityProtocolId, - SecurityProtocolSpecificData, - PayloadBufferSize, - TRUE, - Timeout, - NULL - ); - - return Status; -} diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.h b/MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.h deleted file mode 100644 index 5547e057e..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressBlockIo.h +++ /dev/null @@ -1,415 +0,0 @@ -/** @file - Header file for EFI_BLOCK_IO_PROTOCOL interface. - -Copyright (c) 2013 - 2016, Intel Corporation. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef _EFI_NVME_BLOCKIO_H_ -#define _EFI_NVME_BLOCKIO_H_ - -/** - Reset the Block Device. - - @param This Indicates a pointer to the calling context. - @param ExtendedVerification Driver may perform diagnostics on reset. - - @retval EFI_SUCCESS The device was reset. - @retval EFI_DEVICE_ERROR The device is not functioning properly and could - not be reset. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoReset ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Read BufferSize bytes from Lba into Buffer. - - @param This Indicates a pointer to the calling context. - @param MediaId Id of the media, changes every time the media is replaced. - @param Lba The starting Logical Block Address to read from - @param BufferSize Size of Buffer, must be a multiple of device block size. - @param Buffer A pointer to the destination buffer for the data. The caller is - responsible for either having implicit or explicit ownership of the buffer. - - @retval EFI_SUCCESS The data was read correctly from the device. - @retval EFI_DEVICE_ERROR The device reported an error while performing the read. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. - @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, - or the buffer is not on proper alignment. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoReadBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - OUT VOID *Buffer - ); - -/** - Write BufferSize bytes from Lba into Buffer. - - @param This Indicates a pointer to the calling context. - @param MediaId The media ID that the write request is for. - @param Lba The starting logical block address to be written. The caller is - responsible for writing to only legitimate locations. - @param BufferSize Size of Buffer, must be a multiple of device block size. - @param Buffer A pointer to the source buffer for the data. - - @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_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the 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 -NvmeBlockIoWriteBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This, - IN UINT32 MediaId, - IN EFI_LBA Lba, - IN UINTN BufferSize, - IN VOID *Buffer - ); - -/** - Flush the Block Device. - - @param This Indicates a pointer to the calling context. - - @retval EFI_SUCCESS All outstanding data was written to the device - @retval EFI_DEVICE_ERROR The device reported an error while writing back the data - @retval EFI_NO_MEDIA There is no media in the device. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoFlushBlocks ( - IN EFI_BLOCK_IO_PROTOCOL *This - ); - -/** - Reset the block device hardware. - - @param[in] This Indicates a pointer to the calling context. - @param[in] ExtendedVerification Indicates that the driver may perform a more - exhausive verfication operation of the - device during reset. - - @retval EFI_SUCCESS The device was reset. - @retval EFI_DEVICE_ERROR The device is not functioning properly and could - not be reset. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoResetEx ( - IN EFI_BLOCK_IO2_PROTOCOL *This, - IN BOOLEAN ExtendedVerification - ); - -/** - Read BufferSize bytes from Lba into Buffer. - - This function reads the requested number of blocks from the device. All the - blocks are read, or an error is returned. - If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_or EFI_MEDIA_CHANGED is returned and - non-blocking I/O is being used, the Event associated with this request will - not be signaled. - - @param[in] This Indicates a pointer to the calling context. - @param[in] MediaId Id of the media, changes every time the media is - replaced. - @param[in] Lba The starting Logical Block Address to read from. - @param[in, out] Token A pointer to the token associated with the - transaction. - @param[in] BufferSize Size of Buffer, must be a multiple of device - block size. - @param[out] Buffer A pointer to the destination buffer for the data. - The caller is responsible for either having - implicit or explicit ownership of the buffer. - - @retval EFI_SUCCESS The read request was queued if Token->Event is - not NULL.The data was read correctly from the - device if the Token->Event is NULL. - @retval EFI_DEVICE_ERROR The device reported an error while performing - the read. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of - the intrinsic block size of the device. - @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not - valid, or the buffer is not on proper - alignment. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a - lack of resources. - -**/ -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 - ); - -/** - Write BufferSize bytes from Lba into Buffer. - - This function writes the requested number of blocks to the device. All blocks - are written, or an error is returned.If EFI_DEVICE_ERROR, EFI_NO_MEDIA, - EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED is returned and non-blocking I/O is - being used, the Event associated with this request will not be signaled. - - @param[in] This Indicates a pointer to the calling context. - @param[in] MediaId The media ID that the write request is for. - @param[in] Lba The starting logical block address to be written. - The caller is responsible for writing to only - legitimate locations. - @param[in, out] Token A pointer to the token associated with the - transaction. - @param[in] BufferSize Size of Buffer, must be a multiple of device - block size. - @param[in] Buffer A pointer to the source buffer for the data. - - @retval EFI_SUCCESS The write request was queued if Event is not - NULL. - The data was written correctly to the device if - the Event is NULL. - @retval EFI_WRITE_PROTECTED The device can not be written to. - @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_DEVICE_ERROR The device reported an error while performing - the write. - @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size - of the device. - @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not - valid, or the buffer is not on proper - alignment. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a - lack of resources. - -**/ -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 - ); - -/** - Flush the Block Device. - - If EFI_DEVICE_ERROR, EFI_NO_MEDIA,_EFI_WRITE_PROTECTED or EFI_MEDIA_CHANGED - is returned and non-blocking I/O is being used, the Event associated with - this request will not be signaled. - - @param[in] This Indicates a pointer to the calling context. - @param[in,out] Token A pointer to the token associated with the - transaction. - - @retval EFI_SUCCESS The flush request was queued if Event is not - NULL. - All outstanding data was written correctly to - the device if the Event is NULL. - @retval EFI_DEVICE_ERROR The device reported an error while writting back - the data. - @retval EFI_WRITE_PROTECTED The device cannot be written to. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack - of resources. - -**/ -EFI_STATUS -EFIAPI -NvmeBlockIoFlushBlocksEx ( - IN EFI_BLOCK_IO2_PROTOCOL *This, - IN OUT EFI_BLOCK_IO2_TOKEN *Token - ); - -/** - Send a security protocol command to a device that receives data and/or the result - of one or more commands sent by SendData. - - The ReceiveData function sends a security protocol command to the given MediaId. - The security protocol command sent is defined by SecurityProtocolId and contains - the security protocol specific data SecurityProtocolSpecificData. The function - returns the data from the security protocol command in PayloadBuffer. - - For devices supporting the SCSI command set, the security protocol command is sent - using the SECURITY PROTOCOL IN command defined in SPC-4. - - For devices supporting the ATA command set, the security protocol command is sent - using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize - is non-zero. - - If the PayloadBufferSize is zero, the security protocol command is sent using the - Trusted Non-Data command defined in ATA8-ACS. - - If PayloadBufferSize is too small to store the available data from the security - protocol command, the function shall copy PayloadBufferSize bytes into the - PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL. - - If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero, - the function shall return EFI_INVALID_PARAMETER. - - If the given MediaId does not support security protocol commands, the function shall - return EFI_UNSUPPORTED. If there is no media in the device, the function returns - EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device, - the function returns EFI_MEDIA_CHANGED. - - If the security protocol fails to complete within the Timeout period, the function - shall return EFI_TIMEOUT. - - If the security protocol command completes without an error, the function shall - return EFI_SUCCESS. If the security protocol command completes with an error, the - function shall return EFI_DEVICE_ERROR. - - @param This Indicates a pointer to the calling context. - @param MediaId ID of the medium to receive data from. If there is no - block IO protocol supported by the physical device, the - value of MediaId is undefined. - @param Timeout The timeout, in 100ns units, to use for the execution - of the security protocol command. A Timeout value of 0 - means that this function will wait indefinitely for the - security protocol command to execute. If Timeout is greater - than zero, then this function will return EFI_TIMEOUT - if the time required to execute the receive data command - is greater than Timeout. - @param SecurityProtocolId The value of the "Security Protocol" parameter of - the security protocol command to be sent. - @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter - of the security protocol command to be sent. - @param PayloadBufferSize Size in bytes of the payload data buffer. - @param PayloadBuffer A pointer to a destination buffer to store the security - protocol command specific payload data for the security - protocol command. The caller is responsible for having - either implicit or explicit ownership of the buffer. - @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the - data written to the payload data buffer. - - @retval EFI_SUCCESS The security protocol command completed successfully. - @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available - data from the device. The PayloadBuffer contains the truncated data. - @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands. - @retval EFI_DEVICE_ERROR The security protocol command completed with an error. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and - PayloadBufferSize is non-zero. - @retval EFI_TIMEOUT A timeout occurred while waiting for the security - protocol command to execute. - -**/ -EFI_STATUS -EFIAPI -NvmeStorageSecurityReceiveData ( - IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, - IN UINT32 MediaId, - IN UINT64 Timeout, - IN UINT8 SecurityProtocolId, - IN UINT16 SecurityProtocolSpecificData, - IN UINTN PayloadBufferSize, - OUT VOID *PayloadBuffer, - OUT UINTN *PayloadTransferSize - ); - -/** - Send a security protocol command to a device. - - The SendData function sends a security protocol command containing the payload - PayloadBuffer to the given MediaId. The security protocol command sent is - defined by SecurityProtocolId and contains the security protocol specific data - SecurityProtocolSpecificData. If the underlying protocol command requires a - specific padding for the command payload, the SendData function shall add padding - bytes to the command payload to satisfy the padding requirements. - - For devices supporting the SCSI command set, the security protocol command is sent - using the SECURITY PROTOCOL OUT command defined in SPC-4. - - For devices supporting the ATA command set, the security protocol command is sent - using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize - is non-zero. If the PayloadBufferSize is zero, the security protocol command is - sent using the Trusted Non-Data command defined in ATA8-ACS. - - If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall - return EFI_INVALID_PARAMETER. - - If the given MediaId does not support security protocol commands, the function - shall return EFI_UNSUPPORTED. If there is no media in the device, the function - returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the - device, the function returns EFI_MEDIA_CHANGED. - - If the security protocol fails to complete within the Timeout period, the function - shall return EFI_TIMEOUT. - - If the security protocol command completes without an error, the function shall return - EFI_SUCCESS. If the security protocol command completes with an error, the function - shall return EFI_DEVICE_ERROR. - - @param This Indicates a pointer to the calling context. - @param MediaId ID of the medium to receive data from. If there is no - block IO protocol supported by the physical device, the - value of MediaId is undefined. - @param Timeout The timeout, in 100ns units, to use for the execution - of the security protocol command. A Timeout value of 0 - means that this function will wait indefinitely for the - security protocol command to execute. If Timeout is greater - than zero, then this function will return EFI_TIMEOUT - if the time required to execute the receive data command - is greater than Timeout. - @param SecurityProtocolId The value of the "Security Protocol" parameter of - the security protocol command to be sent. - @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter - of the security protocol command to be sent. - @param PayloadBufferSize Size in bytes of the payload data buffer. - @param PayloadBuffer A pointer to a destination buffer to store the security - protocol command specific payload data for the security - protocol command. - - @retval EFI_SUCCESS The security protocol command completed successfully. - @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands. - @retval EFI_DEVICE_ERROR The security protocol command completed with an error. - @retval EFI_NO_MEDIA There is no media in the device. - @retval EFI_MEDIA_CHANGED The MediaId is not for the current media. - @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero. - @retval EFI_TIMEOUT A timeout occurred while waiting for the security - protocol command to execute. - -**/ -EFI_STATUS -EFIAPI -NvmeStorageSecuritySendData ( - IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This, - IN UINT32 MediaId, - IN UINT64 Timeout, - IN UINT8 SecurityProtocolId, - IN UINT16 SecurityProtocolSpecificData, - IN UINTN PayloadBufferSize, - IN VOID *PayloadBuffer - ); - -#endif diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressBounce.c b/MsvmPkg/NvmExpressDxe/NvmExpressBounce.c deleted file mode 100644 index 155b23a48..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressBounce.c +++ /dev/null @@ -1,623 +0,0 @@ -/** @file - Bounce buffer routines for NVMe device - - Copyright (c) Microsoft Corporation. - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "NvmExpress.h" -#include "NvmExpressBounce.h" - -EFI_HV_IVM_PROTOCOL *mHvIvm; -UINTN mSharedGpaBoundary; -UINT64 mCanonicalizationMask; - -/** - Return true if NVMe should use bounce buffering. - - @param None. - - @returns TRUE if bounce buffering should be used. -**/ -EFI_STATUS -NvmExpressInitializeBounce( - VOID - ) -{ - mSharedGpaBoundary = (UINTN)PcdGet64(PcdIsolationSharedGpaBoundary); - mCanonicalizationMask = PcdGet64(PcdIsolationSharedGpaCanonicalizationBitmask); - return gBS->LocateProtocol(&gEfiHvIvmProtocolGuid, NULL, (VOID **)&mHvIvm); -} - -/** - Return true if NVMe should use bounce buffering. - - @param None. - - @returns TRUE if bounce buffering should be used. -**/ -BOOLEAN -NvmExpressIsBounceActive( - VOID - ) -{ - return IsIsolated(); -} - - -/** - Allocate a large block of memory from EFI for I/O. Mark the memory as host- - visible. Allocate tracking structures to sub-allocate the block into - individual pages. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param[in] BlockByteCount Number of bytes to allocate for I/O. Must be a multiple of EFI_PAGE_SIZE. - - @retval EFI_SUCCESS - @retval EFI_OUT_OF_RESOURCES Memory allocation failures or other failures from hypervisor - page visibility call. -**/ -EFI_STATUS -NvmExpressAllocateBounceBlock( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT32 BlockByteCount - ) -{ - EFI_STATUS status = EFI_INVALID_PARAMETER; - UINT32 pageCount = 0; - UINT32 i = 0; - PNVME_BOUNCE_BLOCK bounceBlock = NULL; - UINT8* nextVa; - UINT64 nextPa; - - DEBUG((EFI_D_VERBOSE, - "%a(%d) Context=%p ByteCount=0x%x\n", - __func__, - __LINE__, - Private, - BlockByteCount)); - - if (BlockByteCount % EFI_PAGE_SIZE) { - status = EFI_INVALID_PARAMETER; - goto Cleanup; - } - - pageCount = BlockByteCount / EFI_PAGE_SIZE; - - bounceBlock = AllocatePool(sizeof(*bounceBlock)); - if (bounceBlock == NULL) { - status = EFI_OUT_OF_RESOURCES; - goto Cleanup; - } - - ZeroMem(bounceBlock, sizeof(*bounceBlock)); - - // Allocate the bounce page memory - - bounceBlock->BlockBase = AllocatePages(pageCount); - if (bounceBlock->BlockBase == NULL) { - status = EFI_OUT_OF_RESOURCES; - goto Cleanup; - } - - bounceBlock->BlockPageCount = pageCount; - ZeroMem(bounceBlock->BlockBase, pageCount * EFI_PAGE_SIZE); - - // Allocate the tracking structures as one - bounceBlock->BouncePageStructureBase = AllocatePool(pageCount * sizeof(NVME_BOUNCE_PAGE)); - if (bounceBlock->BouncePageStructureBase == NULL) { - status = EFI_OUT_OF_RESOURCES; - goto Cleanup; - } - - bounceBlock->FreePageListHead = bounceBlock->BouncePageStructureBase; - nextVa = bounceBlock->BlockBase; - nextPa = (UINT64)nextVa; - - // - // Make these pages visible to the host - // - - if (IsIsolated()) { - status = mHvIvm->MakeAddressRangeHostVisible(mHvIvm, - HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE, - bounceBlock->BlockBase, - pageCount * EFI_PAGE_SIZE, - FALSE, - &bounceBlock->ProtectionHandle); - - if (EFI_ERROR(status)) { - goto Cleanup; - } - - // - // Adjust the address above the shared GPA boundary if required. - // - nextPa += mSharedGpaBoundary; - - // - // Canonicalize the VA. - // - nextVa = (VOID *)(mCanonicalizationMask | nextPa); - bounceBlock->IsHostVisible = TRUE; - } - - for (i = 0; i < pageCount; i++) { - if (i == (pageCount - 1)) { - bounceBlock->BouncePageStructureBase[i].NextBouncePage = NULL; - } else { - bounceBlock->BouncePageStructureBase[i].NextBouncePage = - &bounceBlock->BouncePageStructureBase[i + 1]; - } - - bounceBlock->BouncePageStructureBase[i].BounceBlock = bounceBlock; - bounceBlock->BouncePageStructureBase[i].PageVA = nextVa; - bounceBlock->BouncePageStructureBase[i].HostVisiblePA = nextPa; - nextVa += EFI_PAGE_SIZE; - nextPa += EFI_PAGE_SIZE; - } - - InsertTailList(&Private->BounceBlockListHead, &bounceBlock->BlockListEntry); - status = EFI_SUCCESS; - - Cleanup: - DEBUG((EFI_D_INFO, - "%a (%d) Context=%p bounceBlock=%p status=0x%x\n", - __func__, - __LINE__, - Private, - bounceBlock, - status)); - - if (EFI_ERROR(status)) { - if (bounceBlock) { - NvmExpressFreeBounceBlock(bounceBlock); - bounceBlock = NULL; - } - } - return status; -} - -/** - Free the block of memory allocated for I/O. Marks the memory as not host-visible. - - @param[in] Block Bounce block that needs to be freed. - -**/ -VOID -NvmExpressFreeBounceBlock( - IN PNVME_BOUNCE_BLOCK Block - ) -{ - if (Block->IsHostVisible) { - mHvIvm->MakeAddressRangeNotHostVisible(mHvIvm, &Block->ProtectionHandle); - } - - if (Block->BouncePageStructureBase) { - FreePool(Block->BouncePageStructureBase); - Block->BouncePageStructureBase = NULL; - } - - if (Block->BlockBase) { - FreePages(Block->BlockBase, Block->BlockPageCount); - Block->BlockBase = NULL; - Block->BlockPageCount = 0; - } - - FreePool(Block); -} - -/** - Free all of the large blocks of memory allocated for I/O. Marks the memory - as not host-visible. Frees the associated tracking structures. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - -**/ -VOID -NvmExpressFreeAllBounceBlocks( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) - -{ - PNVME_BOUNCE_BLOCK block; - LIST_ENTRY* entry; - - while (!IsListEmpty(&Private->BounceBlockListHead)) { - - entry = GetFirstNode(&Private->BounceBlockListHead); - RemoveEntryList(entry); - - block = BASE_CR(entry, NVME_BOUNCE_BLOCK, BlockListEntry); - - DEBUG((EFI_D_WARN, - "%a (%d) Context=%p block=%p IsHostVis=%d InUsePageCount=%d BlockBase=%p PageCount=0x%x\n", - __func__, - __LINE__, - Private, - block, - block->IsHostVisible, - block->InUsePageCount, - block->BlockBase, - block->BlockPageCount)); - - NvmExpressFreeBounceBlock(block); - block = NULL; - } -} - -/** - Remove 'PageCount' pre-allocated NVME_BOUNCE_PAGE structures from the - NVME_CONTROLLER_PRIVATE_DATA context and return them in a linked-list. - These PAGE structures will be used in an I/O. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param[in] PageCount Number of NVME_BOUNCE_PAGE structures to acquire from the - NVME_CONTROLLER_PRIVATE_DATA context structure and return to - the caller. - - @retval Linked list of NVME_BOUNCE_PAGE structures or NULL on failure. -**/ -PNVME_BOUNCE_PAGE -NvmExpressAcquireBouncePages( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT32 PageCount - ) -{ - PNVME_BOUNCE_PAGE listHead = NULL; - UINT32 pagesToGo = PageCount; - EFI_STATUS status; - - DEBUG((EFI_D_VERBOSE, - "%a(%d) Context=%p PageCount=%d\n", - __func__, - __LINE__, - Private, - PageCount)); - -Retry: - if (!IsListEmpty(&Private->BounceBlockListHead)) { - LIST_ENTRY* blockListEntry; - - for (blockListEntry = Private->BounceBlockListHead.ForwardLink; - blockListEntry != &Private->BounceBlockListHead; - blockListEntry = blockListEntry->ForwardLink) { - - PNVME_BOUNCE_BLOCK bounceBlock; - bounceBlock = BASE_CR(blockListEntry, NVME_BOUNCE_BLOCK, BlockListEntry); - - while (bounceBlock->FreePageListHead && pagesToGo) { - - PNVME_BOUNCE_PAGE bouncePage; - - bouncePage = bounceBlock->FreePageListHead; - bounceBlock->FreePageListHead = bouncePage->NextBouncePage; - - bouncePage->NextBouncePage = listHead; - listHead = bouncePage; - - bounceBlock->InUsePageCount++; - - pagesToGo--; - } - - if (pagesToGo == 0) { - break; - } - } - - if (pagesToGo) { - UINT32 allocSize = MAX(pagesToGo * EFI_PAGE_SIZE, 32 * EFI_PAGE_SIZE); - - status = NvmExpressAllocateBounceBlock(Private, allocSize); - if (EFI_ERROR(status)) { - DEBUG((EFI_D_WARN, - "%a(%d) Context=%p Bounce block allocation failure\n", - __func__, - __LINE__, - Private)); - goto Exit; - } - goto Retry; - } - } - -Exit: - if (pagesToGo) { - // failed - NvmExpressReleaseBouncePages(Private, listHead); - - DEBUG((EFI_D_WARN, - "%a(%d) Context=%p PageCount=%d Returning=NULL\n", - __func__, - __LINE__, - Private, - PageCount)); - } else { - DEBUG((EFI_D_VERBOSE, - "%a(%d) Context=%p PageCount=%d Returning=%p\n", - __func__, - __LINE__, - Private, - PageCount, - listHead)); - } - return listHead; -} - -/** - Return NVME_BOUNCE_PAGES from a linked list to their 'home' NVME_BOUNCE_BLOCK lists. - Effectively frees these temporary pages for use by another I/O. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param[in] BounceListHead Linked list of one more NVME_BOUNCE_PAGE structures. - -**/ -VOID -NvmExpressReleaseBouncePages( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN OUT PNVME_BOUNCE_PAGE BounceListHead - ) -{ - PNVME_BOUNCE_PAGE page; - UINT32 count = 0; - - while (BounceListHead) { - page = BounceListHead; - BounceListHead = BounceListHead->NextBouncePage; - - page->BounceBlock->InUsePageCount--; - count++; - - page->NextBouncePage = page->BounceBlock->FreePageListHead; - page->BounceBlock->FreePageListHead = page; - } - - DEBUG((EFI_D_VERBOSE, - "%a(%d) Context=%p released PageCount=%d\n", - __func__, - __LINE__, - Private, - count)); - - BounceListHead = NULL; -} - -/** - Copy between the memory pages in the bounce buffers and the client's - buffer respecting the page offsets of the client's buffer. This function - will zero the partial pages at the beginning and end of the BouncePageList. - - @param[in] ExternalBuffer The EFI client's data buffer. Can start at any - @param[in] BufferSize Size of EFI client's data buffer. - @param[in] BouncePageList List of bounce pages (shared with host) - @param[in] CopyToBounce If TRUE, copy from ExternalBuffer into the BouncePageList. - If FALSE, copy from the BouncePageList into ExternalBuffer. - -**/ -VOID -NvmExpressCopyBouncePagesToExternalBuffer( - IN VOID * ExternalBuffer, - IN UINT32 BufferSize, - IN PNVME_BOUNCE_PAGE BouncePageList, - IN BOOLEAN CopyToBounce - ) -{ - UINT64 pageOffset; - PNVME_BOUNCE_PAGE bouncePage; - UINT8* bounceBuffer; - UINT8* bounceBufferEnd; - UINT8* extBuffer; - UINT32 transferToGo; - UINT32 copySize; - - DEBUG((EFI_D_INFO, - "%a(%d) ExternalBuffer.Buffer=%p Size=0x%x BouncePageList=%p CopyToBounce=%d\n", - __func__, - __LINE__, - ExternalBuffer, - BufferSize, - BouncePageList, - CopyToBounce)); - - ASSERT (BouncePageList); - - bouncePage = BouncePageList; - pageOffset = (UINT64)ExternalBuffer % EFI_PAGE_SIZE; - - extBuffer = ExternalBuffer; - transferToGo = BufferSize; - - while (transferToGo) { - ASSERT(bouncePage); - - bounceBuffer = (UINT8*)bouncePage->PageVA; - - // Zero any unused space in buffer we are sharing with the host. - if (CopyToBounce && pageOffset) { - DEBUG((EFI_D_VERBOSE, - "%a(%d) Zero %p size=0x%x\n", - __func__, - __LINE__, - bouncePage->PageVA, - pageOffset)); - ZeroMem(bouncePage->PageVA, pageOffset); - } - - // First page offset - bounceBuffer += pageOffset; - copySize = EFI_PAGE_SIZE - (UINT32)pageOffset; - pageOffset = 0; // no more offsets - - copySize = MIN(copySize, transferToGo); - bounceBufferEnd = bounceBuffer + copySize; - - if (CopyToBounce) { - DEBUG((EFI_D_VERBOSE, - "%a(%d) CopyToBounce dst=%p src=%p size=0x%x\n", - __func__, - __LINE__, - bounceBuffer, - extBuffer, - copySize)); - - CopyMem(bounceBuffer, extBuffer, copySize); - } else { - DEBUG((EFI_D_VERBOSE, - "%a(%d) CopyToExtBuffer dst=%p src=%p size=0x%x\n", - __func__, - __LINE__, - extBuffer, - bounceBuffer, - copySize)); - - CopyMem(extBuffer, bounceBuffer, copySize); - } - - transferToGo -= copySize; - extBuffer += copySize; - - // Zero any unused space in buffer we are sharing with the host. - if (transferToGo == 0 && - CopyToBounce && - ((UINT64)bounceBuffer % EFI_PAGE_SIZE)) { - UINT32 endOffset = (UINT64)bounceBufferEnd % EFI_PAGE_SIZE; - UINT32 zeroSize = EFI_PAGE_SIZE - endOffset; - - DEBUG((EFI_D_VERBOSE, - "%a(%d) Zero %p size=0x%x (from offset=0x%x)\n", - __func__, - __LINE__, - bounceBufferEnd, - zeroSize, - endOffset)); - - ZeroMem(bounceBufferEnd, zeroSize); - } - bouncePage = bouncePage->NextBouncePage; - } - - ASSERT(bouncePage == NULL); // should be all done -} - -/** - Zero initialize host-visible bounce page list. - - @param[in] BouncePageList List of bounce pages (shared with host). - -**/ -VOID -NvmExpressZeroBouncePageList( - IN PNVME_BOUNCE_PAGE BouncePageList - ) -{ - PNVME_BOUNCE_PAGE bouncePage = BouncePageList; - UINT32 pageCount = 0; - - while (bouncePage) { - ZeroMem(bouncePage->PageVA, EFI_PAGE_SIZE); - bouncePage = bouncePage->NextBouncePage; - pageCount++; - } - DEBUG((EFI_D_VERBOSE, "%a(%d) BouncePageList=%p zeroed %d pages\n", - __func__, - __LINE__, - BouncePageList, - pageCount)); -} - - -// -// Page visibility -// - -UINTN -NvmExpressGetSharedPa( - VOID* Address - ) -/** - Given an address, which may be either a VA or a PA, removes any - canonicalization bits and returns the shared GPA corresponding to the - address. - - @param Address Input address. - - @returns Shared GPA. - -**/ -{ - UINTN addr; - - addr = (UINTN)Address; - addr &= ~mCanonicalizationMask; - if (addr < mSharedGpaBoundary) - { - addr += mSharedGpaBoundary; - } - - return addr; -} - -VOID* -NvmExpressGetSharedVa( - VOID* Address - ) -/** - Given an address, which may be either a VA or a PA, returns a canonicalized - pointer pointing to the shared GPA alias. - - @param Address Input address. - - @returns Shared VA pointer. - -**/ -{ - return (VOID*)(NvmExpressGetSharedPa(Address) | mCanonicalizationMask); -} - -EFI_STATUS -NvmExpressMakeAddressRangeShared( - IN OUT NVME_HOST_VISIBILITY_CONTEXT *HostVisibilityContext, - IN OUT VOID *BaseAddress, - IN UINT32 ByteCount - ) -{ - ASSERT(IsIsolated()); - - EFI_STATUS status = mHvIvm->MakeAddressRangeHostVisible(mHvIvm, - HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE, - BaseAddress, - ByteCount, - FALSE, - &HostVisibilityContext->RangeProtectionHandle); - - if (EFI_ERROR(status)) - { - return status; - } - - // - // Adjust the address above the shared GPA boundary. - // - BaseAddress = (UINT8 *)((UINTN)BaseAddress + mSharedGpaBoundary); - - return EFI_SUCCESS; -} - - -VOID -NvmExpressMakeAddressRangePrivate( - IN NVME_HOST_VISIBILITY_CONTEXT *HostVisibilityContext, - IN OUT VOID *AddressRange - ) -{ - ASSERT(IsIsolated()); - - mHvIvm->MakeAddressRangeNotHostVisible(mHvIvm, &HostVisibilityContext->RangeProtectionHandle); - - AddressRange = (VOID *)((UINT64)AddressRange & ~mCanonicalizationMask); - if ((UINTN)AddressRange >= mSharedGpaBoundary) { - AddressRange = (VOID *)((UINTN)AddressRange - mSharedGpaBoundary); - } -} diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressBounce.h b/MsvmPkg/NvmExpressDxe/NvmExpressBounce.h deleted file mode 100644 index 224c4bc90..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressBounce.h +++ /dev/null @@ -1,205 +0,0 @@ -/** @file - Bounce buffer routines for NVMe device - - Copyright (c) Microsoft Corporation. - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#pragma once - -#include - -#include - -#include "NvmExpress.h" - -// -// Nvme bounce buffer support. -// - -#define NVME_BOUNCE_BLOCK_SIZE (32 * EFI_PAGE_SIZE) - -typedef struct _NVME_BOUNCE_BLOCK -{ - LIST_ENTRY BlockListEntry; - - struct _NVME_BOUNCE_PAGE *FreePageListHead; - - UINT32 InUsePageCount; - BOOLEAN IsHostVisible; - - VOID * BlockBase; - UINT32 BlockPageCount; - EFI_HV_PROTECTION_HANDLE ProtectionHandle; - - // Allocate associated _NVME_BOUNCE_PAGE as a large block - struct _NVME_BOUNCE_PAGE *BouncePageStructureBase; -} NVME_BOUNCE_BLOCK, *PNVME_BOUNCE_BLOCK; - -// -// NVME_BOUNCE_PAGE - represents one guest physical page of a block. -// Units of pages are allocated to a vmbus packet as required and -// returned to the 'block pool' when not in use. -// -typedef struct _NVME_BOUNCE_PAGE -{ - struct _NVME_BOUNCE_PAGE* NextBouncePage; - struct _NVME_BOUNCE_BLOCK* BounceBlock; - VOID * PageVA; - UINT64 HostVisiblePA; -} NVME_BOUNCE_PAGE, *PNVME_BOUNCE_PAGE; - -typedef struct _NVME_PAGE_VISIBILITY_CONTEXT -{ - EFI_HV_PROTECTION_HANDLE RangeProtectionHandle; -} NVME_HOST_VISIBILITY_CONTEXT; - - -EFI_STATUS -NvmExpressInitializeBounce( - VOID - ); - -/** - Return true if NVMe should use bounce buffering. - - @param None. - - @returns TRUE if bounce buffering should be used. -**/ -BOOLEAN -NvmExpressIsBounceActive( - VOID - ); - -/** - Allocate a large block of memory from EFI for I/O. Mark the memory as host- - visible. Allocate tracking structures to sub-allocate the block into - individual pages. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param[in] BlockByteCount Number of bytes to allocate for I/O. Must be a multiple of EFI_PAGE_SIZE. - - @retval EFI_SUCCESS - @retval EFI_OUT_OF_RESOURCES Memory allocation failures or other failures from hypervisor - page visibility call. -**/ -EFI_STATUS -NvmExpressAllocateBounceBlock( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT32 BlockByteCount - ); - -/** - Free the block of memory allocated for I/O. Marks the memory as not host-visible. - - @param[in] Block Bounce block that needs to be freed. - -**/ -VOID -NvmExpressFreeBounceBlock( - IN PNVME_BOUNCE_BLOCK Block - ); - -/** - Free all of the large blocks of memory allocated for I/O. Marks the memory - as not host-visible. Frees the associated tracking structures. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - -**/ -VOID -NvmExpressFreeAllBounceBlocks( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ); - -/** - Remove 'PageCount' pre-allocated NVME_BOUNCE_PAGE structures from the - NVME_CONTROLLER_PRIVATE_DATA context and return them in a linked-list. - These PAGE structures will be used in an I/O. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param[in] PageCount Number of NVME_BOUNCE_PAGE structures to acquire from the - NVME_CONTROLLER_PRIVATE_DATA context structure and return to - the caller. - - @retval Linked list of NVME_BOUNCE_PAGE structures or NULL on failure. -**/ -PNVME_BOUNCE_PAGE -NvmExpressAcquireBouncePages( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT32 PageCount - ); - -/** - Return NVME_BOUNCE_PAGES from a linked list to their 'home' NVME_BOUNCE_BLOCK lists. - Effectively frees these temporary pages for use by another I/O. - - @param[in] Private Pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param[in] BounceListHead Linked list of one more NVME_BOUNCE_PAGE structures. - -**/ -VOID -NvmExpressReleaseBouncePages( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN OUT PNVME_BOUNCE_PAGE BounceListHead - ); - -/** - Copy between the memory pages in the bounce buffers and the client's - buffer respecting the page offsets of the client's buffer. This function - will zero the partial pages at the beginning and end of the BouncePageList. - - @param[in] ExternalBuffer The EFI client's data buffer. Can start at any - @param[in] BufferSize Size of EFI client's data buffer. - @param[in] BouncePageList List of bounce pages (shared with host) - @param[in] CopyToBounce If TRUE, copy from ExternalBuffer into the BouncePageList. - If FALSE, copy from the BouncePageList into ExternalBuffer. - -**/ -VOID -NvmExpressCopyBouncePagesToExternalBuffer( - IN VOID * ExternalBuffer, - IN UINT32 BufferSize, - IN PNVME_BOUNCE_PAGE BouncePageList, - IN BOOLEAN CopyToBounce - ); - -/** - Zero initialize host-visible bounce page list. - - @param[in] BouncePageList List of bounce pages (shared with host). - -**/ -VOID -NvmExpressZeroBouncePageList( - IN PNVME_BOUNCE_PAGE BouncePageList - ); - - -// -// Page visibility -// -UINTN -NvmExpressGetSharedPa( - VOID* Address - ); - -VOID* -NvmExpressGetSharedVa( - VOID* Address - ); - -EFI_STATUS -NvmExpressMakeAddressRangeShared( - IN OUT NVME_HOST_VISIBILITY_CONTEXT *HostVisibilityContext, - IN OUT VOID *BaseAddress, - IN UINT32 ByteCount - ); - -VOID -NvmExpressMakeAddressRangePrivate( - IN NVME_HOST_VISIBILITY_CONTEXT *HostVisibilityContext, - IN OUT VOID *AddressRange - ); \ No newline at end of file diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.c b/MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.c deleted file mode 100644 index 9a5ca6730..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.c +++ /dev/null @@ -1,153 +0,0 @@ -/** @file - This file is used to implement the EFI_DISK_INFO_PROTOCOL interface.. - - Copyright (c) 2013, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "NvmExpress.h" - -EFI_DISK_INFO_PROTOCOL gNvmExpressDiskInfoProtocolTemplate = { - EFI_DISK_INFO_NVME_INTERFACE_GUID, - NvmExpressDiskInfoInquiry, - NvmExpressDiskInfoIdentify, - NvmExpressDiskInfoSenseData, - NvmExpressDiskInfoWhichIde -}; - -/** - Initialize the installation of DiskInfo protocol. - - This function prepares for the installation of DiskInfo protocol on the child handle. - By default, it installs DiskInfo protocol with NVME interface GUID. - - @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA. - -**/ -VOID -InitializeDiskInfo ( - IN NVME_DEVICE_PRIVATE_DATA *Device - ) -{ - CopyMem (&Device->DiskInfo, &gNvmExpressDiskInfoProtocolTemplate, sizeof (EFI_DISK_INFO_PROTOCOL)); -} - -/** - Provides inquiry information for the controller type. - - This function is used to get inquiry data. Data format - of Identify data is defined by the Interface GUID. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param[in, out] InquiryData Pointer to a buffer for the inquiry data. - @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading InquiryData from device - @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoInquiry ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *InquiryData, - IN OUT UINT32 *InquiryDataSize - ) -{ - return EFI_NOT_FOUND; -} - -/** - Provides identify information for the controller type. - - This function is used to get identify data. Data format - of Identify data is defined by the Interface GUID. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL - instance. - @param[in, out] IdentifyData Pointer to a buffer for the identify data. - @param[in, out] IdentifyDataSize Pointer to the value for the identify data - size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading IdentifyData from device - @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoIdentify ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *IdentifyData, - IN OUT UINT32 *IdentifyDataSize - ) -{ - EFI_STATUS Status; - NVME_DEVICE_PRIVATE_DATA *Device; - - Device = NVME_DEVICE_PRIVATE_DATA_FROM_DISK_INFO (This); - - Status = EFI_BUFFER_TOO_SMALL; - if (*IdentifyDataSize >= sizeof (Device->NamespaceData)) { - Status = EFI_SUCCESS; - CopyMem (IdentifyData, &Device->NamespaceData, sizeof (Device->NamespaceData)); - } - - *IdentifyDataSize = sizeof (Device->NamespaceData); - return Status; -} - -/** - Provides sense data information for the controller type. - - This function is used to get sense data. - Data format of Sense data is defined by the Interface GUID. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param[in, out] SenseData Pointer to the SenseData. - @param[in, out] SenseDataSize Size of SenseData in bytes. - @param[out] SenseDataNumber Pointer to the value for the sense data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class. - @retval EFI_DEVICE_ERROR Error reading SenseData from device. - @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoSenseData ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *SenseData, - IN OUT UINT32 *SenseDataSize, - OUT UINT8 *SenseDataNumber - ) -{ - return EFI_NOT_FOUND; -} - -/** - This function is used to get controller information. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary. - @param[out] IdeDevice Pointer to the Ide Device number. Master or slave. - - @retval EFI_SUCCESS IdeChannel and IdeDevice are valid. - @retval EFI_UNSUPPORTED This is not an IDE device. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoWhichIde ( - IN EFI_DISK_INFO_PROTOCOL *This, - OUT UINT32 *IdeChannel, - OUT UINT32 *IdeDevice - ) -{ - return EFI_UNSUPPORTED; -} diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.h b/MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.h deleted file mode 100644 index 22135ca26..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressDiskInfo.h +++ /dev/null @@ -1,121 +0,0 @@ -/** @file - Header file for EFI_DISK_INFO_PROTOCOL interface. - -Copyright (c) 2013, Intel Corporation. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef _NVME_DISKINFO_H_ -#define _NVME_DISKINFO_H_ - -/** - Initialize the installation of DiskInfo protocol. - - This function prepares for the installation of DiskInfo protocol on the child handle. - By default, it installs DiskInfo protocol with NVME interface GUID. - - @param[in] Device The pointer of NVME_DEVICE_PRIVATE_DATA. - -**/ -VOID -InitializeDiskInfo ( - IN NVME_DEVICE_PRIVATE_DATA *Device - ); - -/** - Provides inquiry information for the controller type. - - This function is used to get inquiry data. Data format - of Identify data is defined by the Interface GUID. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param[in, out] InquiryData Pointer to a buffer for the inquiry data. - @param[in, out] InquiryDataSize Pointer to the value for the inquiry data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading InquiryData from device - @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoInquiry ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *InquiryData, - IN OUT UINT32 *InquiryDataSize - ); - -/** - Provides identify information for the controller type. - - This function is used to get identify data. Data format - of Identify data is defined by the Interface GUID. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL - instance. - @param[in, out] IdentifyData Pointer to a buffer for the identify data. - @param[in, out] IdentifyDataSize Pointer to the value for the identify data - size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class - @retval EFI_DEVICE_ERROR Error reading IdentifyData from device - @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoIdentify ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *IdentifyData, - IN OUT UINT32 *IdentifyDataSize - ); - -/** - Provides sense data information for the controller type. - - This function is used to get sense data. - Data format of Sense data is defined by the Interface GUID. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param[in, out] SenseData Pointer to the SenseData. - @param[in, out] SenseDataSize Size of SenseData in bytes. - @param[out] SenseDataNumber Pointer to the value for the sense data size. - - @retval EFI_SUCCESS The command was accepted without any errors. - @retval EFI_NOT_FOUND Device does not support this data class. - @retval EFI_DEVICE_ERROR Error reading SenseData from device. - @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoSenseData ( - IN EFI_DISK_INFO_PROTOCOL *This, - IN OUT VOID *SenseData, - IN OUT UINT32 *SenseDataSize, - OUT UINT8 *SenseDataNumber - ); - -/** - This function is used to get controller information. - - @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance. - @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary. - @param[out] IdeDevice Pointer to the Ide Device number. Master or slave. - - @retval EFI_SUCCESS IdeChannel and IdeDevice are valid. - @retval EFI_UNSUPPORTED This is not an IDE device. - -**/ -EFI_STATUS -EFIAPI -NvmExpressDiskInfoWhichIde ( - IN EFI_DISK_INFO_PROTOCOL *This, - OUT UINT32 *IdeChannel, - OUT UINT32 *IdeDevice - ); - -#endif diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf b/MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf deleted file mode 100644 index 3e99b735c..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressDxe.inf +++ /dev/null @@ -1,101 +0,0 @@ -## @file -# NVM Express Host Controller Module. -# -# NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows -# NVM Express specification. -# -# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.
-# Copyright (c) Microsoft Corporation.
-# SPDX-License-Identifier: BSD-2-Clause-Patent -# -## - -#Override : 00000002 | MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf | bc15ab4a6687a3445fd2152860f80fe7 | 2026-04-28T00-00-00 | 3d43ac3575cdd6ffa7ac36c7ff50d190c8a58097 - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = NvmExpressDxe - MODULE_UNI_FILE = NvmExpressDxe.uni - FILE_GUID = 5BE3BDF4-53CF-46a3-A6A9-73C34A6E5EE3 - MODULE_TYPE = UEFI_DRIVER - VERSION_STRING = 1.0 - ENTRY_POINT = NvmExpressDriverEntry - UNLOAD_IMAGE = NvmExpressUnload - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 EBC -# -# DRIVER_BINDING = gNvmExpressDriverBinding -# COMPONENT_NAME = gNvmExpressComponentName -# COMPONENT_NAME2 = gNvmExpressComponentName2 - -[Sources] - NvmExpressBlockIo.c - NvmExpressBlockIo.h - ComponentName.c - NvmExpress.c - NvmExpress.h - NvmExpressBounce.c ## MS_HYP_CHANGE - NvmExpressDiskInfo.c - NvmExpressDiskInfo.h - NvmExpressHci.c - NvmExpressHci.h - NvmExpressPassthru.c - NvmExpressMediaSanitize.c - NvmExpressMediaSanitize.h - -[Guids] - gNVMeEnableStartEventGroupGuid - gNVMeEnableCompleteEventGroupGuid - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - MsvmPkg/MsvmPkg.dec ## MS_HYP_CHANGE - -[LibraryClasses] - BaseMemoryLib - BaseLib - DebugLib - DevicePathLib - IsolationLib ## MS_HYP_CHANGE - MemoryAllocationLib - UefiDriverEntryPoint - UefiBootServicesTableLib - UefiLib - PrintLib - ReportStatusCodeLib - -[Protocols] - gEfiPciIoProtocolGuid ## TO_START - ## BY_START - ## TO_START - gEfiDevicePathProtocolGuid - gEfiNvmExpressPassThruProtocolGuid ## BY_START - gEfiBlockIoProtocolGuid ## BY_START - gEfiBlockIo2ProtocolGuid ## BY_START - gEfiDiskInfoProtocolGuid ## BY_START - gEfiStorageSecurityCommandProtocolGuid ## BY_START - gEfiDriverSupportedEfiVersionProtocolGuid ## PRODUCES - gMediaSanitizeProtocolGuid ## PRODUCES - gEfiResetNotificationProtocolGuid ## CONSUMES - gEfiHvIvmProtocolGuid ## CONSUMES ## MS_HYP_CHANGE - -[Pcd] - ## MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - gEfiMdeModulePkgTokenSpaceGuid.PcdSupportAlternativeQueueSize ## CONSUMES - ## MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - ## MU_CHANGE [BEGIN] - NVMe namespace filtering - gEfiMdeModulePkgTokenSpaceGuid.PcdNvmeNamespaceFilterId ## CONSUMES - ## MU_CHANGE [END] - NVMe namespace filtering - gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaBoundary ## MS_HYP_CHANGE - gMsvmPkgTokenSpaceGuid.PcdIsolationSharedGpaCanonicalizationBitmask ## MS_HYP_CHANGE - -# [Event] -# EVENT_TYPE_RELATIVE_TIMER ## SOMETIMES_CONSUMES -# - -[UserExtensions.TianoCore."ExtraFiles"] - NvmExpressDxeExtra.uni diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressDxe.uni b/MsvmPkg/NvmExpressDxe/NvmExpressDxe.uni deleted file mode 100644 index 829be6bbe..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressDxe.uni +++ /dev/null @@ -1,17 +0,0 @@ -// /** @file -// NVM Express Host Controller Module. -// -// NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows -// NVM Express specification. -// -// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
-// -// SPDX-License-Identifier: BSD-2-Clause-Patent -// -// **/ - - -#string STR_MODULE_ABSTRACT #language en-US "NVM Express Host Controller Module" - -#string STR_MODULE_DESCRIPTION #language en-US "NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows NVM Express specification." - diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressDxeExtra.uni b/MsvmPkg/NvmExpressDxe/NvmExpressDxeExtra.uni deleted file mode 100644 index c74e13d87..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressDxeExtra.uni +++ /dev/null @@ -1,14 +0,0 @@ -// /** @file -// NvmExpressDxe Localized Strings and Content -// -// Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.
-// -// SPDX-License-Identifier: BSD-2-Clause-Patent -// -// **/ - -#string STR_PROPERTIES_MODULE_NAME -#language en-US -"NVM Express DXE Driver" - - diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressHci.c b/MsvmPkg/NvmExpressDxe/NvmExpressHci.c deleted file mode 100644 index 91b4d20cd..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressHci.c +++ /dev/null @@ -1,1815 +0,0 @@ -/** @file - NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows - NVM Express specification. - - Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "NvmExpress.h" -#include - -#define NVME_SHUTDOWN_PROCESS_TIMEOUT 45 - -// -// The number of NVME controllers managed by this driver, used by -// NvmeRegisterShutdownNotification() and NvmeUnregisterShutdownNotification(). -// -UINTN mNvmeControllerNumber = 0; - -/** - Read Nvm Express controller capability register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Cap The buffer used to store capability register content. - - @return EFI_SUCCESS Successfully read the controller capability register content. - @return EFI_DEVICE_ERROR Fail to read the controller capability register. - -**/ -EFI_STATUS -ReadNvmeControllerCapabilities ( - // MU_CHANGE [BEGIN] - Correct Cap parameter modifier - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - OUT NVME_CAP *Cap - // MU_CHANGE [END] - Correct Cap parameter modifier - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT64 Data; - - PciIo = Private->PciIo; - Status = PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_CAP_OFFSET, - 2, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - WriteUnaligned64 ((UINT64 *)Cap, Data); - return EFI_SUCCESS; -} - -/** - Read Nvm Express controller configuration register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Cc The buffer used to store configuration register content. - - @return EFI_SUCCESS Successfully read the controller configuration register content. - @return EFI_DEVICE_ERROR Fail to read the controller configuration register. - -**/ -EFI_STATUS -ReadNvmeControllerConfiguration ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN NVME_CC *Cc - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT32 Data; - - PciIo = Private->PciIo; - Status = PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_CC_OFFSET, - 1, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - WriteUnaligned32 ((UINT32 *)Cc, Data); - return EFI_SUCCESS; -} - -/** - Write Nvm Express controller configuration register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Cc The buffer used to store the content to be written into configuration register. - - @return EFI_SUCCESS Successfully write data into the controller configuration register. - @return EFI_DEVICE_ERROR Fail to write data into the controller configuration register. - -**/ -EFI_STATUS -WriteNvmeControllerConfiguration ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN NVME_CC *Cc - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT32 Data; - - PciIo = Private->PciIo; - Data = ReadUnaligned32 ((UINT32 *)Cc); - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_CC_OFFSET, - 1, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - DEBUG ((DEBUG_INFO, "Cc.En: %d\n", Cc->En)); - DEBUG ((DEBUG_INFO, "Cc.Css: %d\n", Cc->Css)); - DEBUG ((DEBUG_INFO, "Cc.Mps: %d\n", Cc->Mps)); - DEBUG ((DEBUG_INFO, "Cc.Ams: %d\n", Cc->Ams)); - DEBUG ((DEBUG_INFO, "Cc.Shn: %d\n", Cc->Shn)); - DEBUG ((DEBUG_INFO, "Cc.Iosqes: %d\n", Cc->Iosqes)); - DEBUG ((DEBUG_INFO, "Cc.Iocqes: %d\n", Cc->Iocqes)); - - return EFI_SUCCESS; -} - -/** - Read Nvm Express controller status register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Csts The buffer used to store status register content. - - @return EFI_SUCCESS Successfully read the controller status register content. - @return EFI_DEVICE_ERROR Fail to read the controller status register. - -**/ -EFI_STATUS -ReadNvmeControllerStatus ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN NVME_CSTS *Csts - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT32 Data; - - PciIo = Private->PciIo; - Status = PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_CSTS_OFFSET, - 1, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - WriteUnaligned32 ((UINT32 *)Csts, Data); - return EFI_SUCCESS; -} - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Read Nvm Express admin queue attributes register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Aqa The buffer used to store the content to be read from admin queue attributes register. - - @return EFI_SUCCESS Successfully read data from the admin queue attributes register. - @return EFI_DEVICE_ERROR Fail to read data from the admin queue attributes register. - -**/ -EFI_STATUS -ReadNvmeAdminQueueAttributes ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - OUT NVME_AQA *Aqa - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT32 Data; - - PciIo = Private->PciIo; - Status = PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_AQA_OFFSET, - 1, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - WriteUnaligned32 ((UINT32 *)Aqa, Data); - - DEBUG ((DEBUG_INFO, "%a: Admin Submission Queue Size (Number of Entries): %d\n", __func__, Aqa->Asqs)); - DEBUG ((DEBUG_INFO, "%a: Admin Completion Queue Size (Number of Entries): %d\n", __func__, Aqa->Acqs)); - - return EFI_SUCCESS; -} - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -/** - Write Nvm Express admin queue attributes register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Aqa The buffer used to store the content to be written into admin queue attributes register. - - @return EFI_SUCCESS Successfully write data into the admin queue attributes register. - @return EFI_DEVICE_ERROR Fail to write data into the admin queue attributes register. - -**/ -EFI_STATUS -WriteNvmeAdminQueueAttributes ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN NVME_AQA *Aqa - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT32 Data; - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // - // Save Aqa to Private data for later use. - // - Private->SqData[0].NumberOfEntries = Aqa->Asqs; - Private->CqData[0].NumberOfEntries = Aqa->Acqs; - // MU_CHANGE [END] - Allocate IO Queue Buffer - - PciIo = Private->PciIo; - Data = ReadUnaligned32 ((UINT32 *)Aqa); - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_AQA_OFFSET, - 1, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - DEBUG ((DEBUG_INFO, "Aqa.Asqs: %d\n", Aqa->Asqs)); - DEBUG ((DEBUG_INFO, "Aqa.Acqs: %d\n", Aqa->Acqs)); - - return EFI_SUCCESS; -} - -/** - Write Nvm Express admin submission queue base address register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Asq The buffer used to store the content to be written into admin submission queue base address register. - - @return EFI_SUCCESS Successfully write data into the admin submission queue base address register. - @return EFI_DEVICE_ERROR Fail to write data into the admin submission queue base address register. - -**/ -EFI_STATUS -WriteNvmeAdminSubmissionQueueBaseAddress ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN NVME_ASQ *Asq - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT64 Data; - - PciIo = Private->PciIo; - Data = ReadUnaligned64 ((UINT64 *)Asq); - - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_ASQ_OFFSET, - 2, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - DEBUG ((DEBUG_INFO, "Asq: %lx\n", *Asq)); - - return EFI_SUCCESS; -} - -/** - Write Nvm Express admin completion queue base address register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Acq The buffer used to store the content to be written into admin completion queue base address register. - - @return EFI_SUCCESS Successfully write data into the admin completion queue base address register. - @return EFI_DEVICE_ERROR Fail to write data into the admin completion queue base address register. - -**/ -EFI_STATUS -WriteNvmeAdminCompletionQueueBaseAddress ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN NVME_ACQ *Acq - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_STATUS Status; - UINT64 Data; - - PciIo = Private->PciIo; - Data = ReadUnaligned64 ((UINT64 *)Acq); - - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_ACQ_OFFSET, - 2, - &Data - ); - - if (EFI_ERROR (Status)) { - return Status; - } - - DEBUG ((DEBUG_INFO, "Acq: %lxh\n", *Acq)); - - return EFI_SUCCESS; -} - -/** - Disable the Nvm Express controller. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @return EFI_SUCCESS Successfully disable the controller. - @return EFI_DEVICE_ERROR Fail to disable the controller. - -**/ -EFI_STATUS -NvmeDisableController ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - NVME_CC Cc; - NVME_CSTS Csts; - EFI_STATUS Status; - UINT32 Index; - UINT8 Timeout; - - // - // Read Controller Configuration Register. - // - Status = ReadNvmeControllerConfiguration (Private, &Cc); - if (EFI_ERROR (Status)) { - return Status; - } - - Cc.En = 0; - - // - // Disable the controller. - // - Status = WriteNvmeControllerConfiguration (Private, &Cc); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to transition from 1 to 0 after - // Cc.Enable transition from 1 to 0. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To. - // - if (Private->Cap.To == 0) { - Timeout = 1; - } else { - Timeout = Private->Cap.To; - } - - for (Index = (Timeout * 500); Index != 0; --Index) { - gBS->Stall (1000); - - // - // Check if the controller is initialized - // - Status = ReadNvmeControllerStatus (Private, &Csts); - - if (EFI_ERROR (Status)) { - return Status; - } - - if (Csts.Rdy == 0) { - break; - } - } - - if (Index == 0) { - Status = EFI_DEVICE_ERROR; - REPORT_STATUS_CODE ( - (EFI_ERROR_CODE | EFI_ERROR_MAJOR), - (EFI_IO_BUS_SCSI | EFI_IOB_EC_INTERFACE_ERROR) - ); - } - - DEBUG ((DEBUG_INFO, "NVMe controller is disabled with status [%r].\n", Status)); - return Status; -} - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Enable the Nvm Express controller. Allocate and write the Controller Configuration data. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param IoSqEs The I/O Submission Queue Entry Size. - @param IoCqEs The I/O Completion Queue Entry Size. - - @return EFI_SUCCESS Successfully enable the controller. - @return EFI_DEVICE_ERROR Fail to enable the controller. - @return EFI_TIMEOUT Fail to enable the controller in given time slot. - -**/ -EFI_STATUS -NvmeEnableController ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT8 IoSqEs, - IN UINT8 IoCqEs - ) -{ - // MU_CHANGE [END] - Allocate IO Queue Buffer - NVME_CC Cc; - NVME_CSTS Csts; - EFI_STATUS Status; - UINT32 Index; - UINT8 Timeout; - - EfiEventGroupSignal (&gNVMeEnableStartEventGroupGuid); - - // - // Enable the controller. - // CC.AMS, CC.MPS and CC.CSS are all set to 0. - // - ZeroMem (&Cc, sizeof (NVME_CC)); - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - Cc.En = 1; - Cc.Iosqes = IoSqEs; - Cc.Iocqes = IoCqEs; - // MU_CHANGE [END] - Allocate IO Queue Buffer - - Status = WriteNvmeControllerConfiguration (Private, &Cc); - if (EFI_ERROR (Status)) { - goto Cleanup; - } - - // - // Cap.To specifies max delay time in 500ms increments for Csts.Rdy to set after - // Cc.Enable. Loop produces a 1 millisecond delay per itteration, up to 500 * Cap.To. - // - if (Private->Cap.To == 0) { - Timeout = 1; - } else { - Timeout = Private->Cap.To; - } - - for (Index = (Timeout * 500); Index != 0; --Index) { - gBS->Stall (1000); - - // - // Check if the controller is initialized - // - Status = ReadNvmeControllerStatus (Private, &Csts); - - if (EFI_ERROR (Status)) { - goto Cleanup; - } - - if (Csts.Rdy) { - break; - } - } - - if (Index == 0) { - Status = EFI_TIMEOUT; - REPORT_STATUS_CODE ( - (EFI_ERROR_CODE | EFI_ERROR_MAJOR), - (EFI_IO_BUS_SCSI | EFI_IOB_EC_INTERFACE_ERROR) - ); - } - - DEBUG ((DEBUG_INFO, "NVMe controller is enabled with status [%r].\n", Status)); - -Cleanup: - EfiEventGroupSignal (&gNVMeEnableCompleteEventGroupGuid); - return Status; -} - -/** - Get identify controller data. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Buffer The buffer used to store the identify controller data. - - @return EFI_SUCCESS Successfully get the identify controller data. - @return EFI_DEVICE_ERROR Fail to get the identify controller data. - -**/ -EFI_STATUS -NvmeIdentifyController ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN VOID *Buffer - ) -{ - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - - ZeroMem (&CommandPacket, sizeof (EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET)); - ZeroMem (&Command, sizeof (EFI_NVM_EXPRESS_COMMAND)); - ZeroMem (&Completion, sizeof (EFI_NVM_EXPRESS_COMPLETION)); - - Command.Cdw0.Opcode = NVME_ADMIN_IDENTIFY_CMD; - // - // According to Nvm Express 1.1 spec Figure 38, When not used, the field shall be cleared to 0h. - // For the Identify command, the Namespace Identifier is only used for the Namespace data structure. - // - Command.Nsid = 0; - - CommandPacket.NvmeCmd = &Command; - CommandPacket.NvmeCompletion = &Completion; - CommandPacket.TransferBuffer = Buffer; - CommandPacket.TransferLength = sizeof (NVME_ADMIN_CONTROLLER_DATA); - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket.QueueType = NVME_ADMIN_QUEUE; - // - // Set bit 0 (Cns bit) to 1 to identify a controller - // - Command.Cdw10 = 1; - Command.Flags = CDW10_VALID; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - NVME_CONTROLLER_ID, - &CommandPacket, - NULL - ); - - return Status; -} - -/** - Get specified identify namespace data. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param NamespaceId The specified namespace identifier. - @param Buffer The buffer used to store the identify namespace data. - - @return EFI_SUCCESS Successfully get the identify namespace data. - @return EFI_DEVICE_ERROR Fail to get the identify namespace data. - -**/ -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; - EFI_STATUS Status; - - 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; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - NamespaceId, - &CommandPacket, - NULL - ); - - return Status; -} - -// MU_CHANGE [BEGIN] - Request Number of Queues from Controller - -/** - Send the Set Features Command to the controller for the number of queues requested. - Note that the number of queues allocated may be different from the number of queues requested. - The number of data queue pairs allocated is returned and stored in the controller private data structure - using the NumberOfIoQueuePairs field. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Ndqpr The number of data queue pairs requested. - - @return EFI_SUCCESS Successfully set the number of queues. - @return EFI_DEVICE_ERROR Fail to set the number of queues. - -**/ -EFI_STATUS -NvmeSetFeaturesNumberOfQueues ( - IN OUT NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT16 Ndqpr - ) -{ - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - NVME_ADMIN_SET_FEATURES_CDW10 SetFeatures; - NVME_ADMIN_SET_FEATURES_NUM_QUEUES NumberOfQueuesRequested; - NVME_ADMIN_SET_FEATURES_NUM_QUEUES NumberOfQueuesAllocated; - - Status = EFI_SUCCESS; - - if (Ndqpr == 0) { - DEBUG ((DEBUG_ERROR, "Number of Data Queue Pairs Requested cannot be 0\n")); - return EFI_INVALID_PARAMETER; - } - - 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 (&SetFeatures, sizeof (NVME_ADMIN_SET_FEATURES)); - ZeroMem (&NumberOfQueuesRequested, sizeof (NVME_ADMIN_SET_FEATURES_NUM_QUEUES)); - ZeroMem (&NumberOfQueuesAllocated, sizeof (NVME_ADMIN_SET_FEATURES_NUM_QUEUES)); - - CommandPacket.NvmeCmd = &Command; - CommandPacket.NvmeCompletion = &Completion; - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket.QueueType = NVME_ADMIN_QUEUE; - Command.Nsid = 0; // NSID must be set to 0h or FFFFFFFFh for an admin command - Command.Cdw0.Opcode = NVME_ADMIN_SET_FEATURES_CMD; - - // Populate the Set Features Cdw10 and Cdw11 according to Nvm Express 1.3d Spec - // Note we subtract 1 from the requested number of queues to get the 0-based value - SetFeatures.Bits.Fid = NVME_FEATURE_NUMBER_OF_QUEUES; - NumberOfQueuesRequested.Bits.Ncq = Ndqpr - 1; - NumberOfQueuesRequested.Bits.Nsq = Ndqpr - 1; - CommandPacket.NvmeCmd->Cdw10 = SetFeatures.Uint32; - CommandPacket.NvmeCmd->Cdw11 = NumberOfQueuesRequested.Uint32; - - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID; - - DEBUG ((DEBUG_INFO, "Number of Data Queue Pairs Requested: %d\n", Ndqpr)); - - // Send the Set Features Command for Number of Queues - Status = Private->Passthru.PassThru ( - &Private->Passthru, - 0, - &CommandPacket, - NULL - ); - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Set Features Command for Number of Queues failed with Status %r\n", Status)); - return Status; - } - - // - // Save the number of queues allocated, adding 1 to account for it being a 0-based value. - // E.g. if 1 pair of data queues is allocated Nsq=0, Ncq=0, then NumberOfIoQueuePairs=1. - // These numbers do not include the admin queues. - // - NumberOfQueuesAllocated.Uint32 = CommandPacket.NvmeCompletion->DW0; - DEBUG ((DEBUG_INFO, "Number of Data Queue Pairs Allocated By Controller: %d, \n", (NumberOfQueuesAllocated.Bits.Nsq + 1))); - if ((NumberOfQueuesAllocated.Bits.Nsq + 1) > Ndqpr) { - // This driver at maximum supports 2 pairs of data queues. So we will take the minimum of the requested and allocated values. - Private->NumberOfIoQueuePairs = Ndqpr; - } else { - Private->NumberOfIoQueuePairs = NumberOfQueuesAllocated.Bits.Nsq + 1; - } - - DEBUG ((DEBUG_INFO, "Number of Data Queue Pairs Supported By Driver: %d, \n", Private->NumberOfIoQueuePairs)); - return Status; -} - -// MU_CHANGE [END] - Request Number of Queues from Controller - -/** - Create io completion queue(s). - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @return EFI_SUCCESS Successfully create io completion queue. - @return EFI_DEVICE_ERROR Fail to create io completion queue. - -**/ -EFI_STATUS -NvmeCreateIoCompletionQueue ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - NVME_ADMIN_CRIOCQ CrIoCq; - UINT32 Index; - UINT16 QueueSize; - - Status = EFI_SUCCESS; - Private->CreateIoQueue = TRUE; - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - // Start from Index 1 because Index 0 is reserved for admin queue - for (Index = 1; Index <= Private->NumberOfIoQueuePairs; Index++) { - // MU_CHANGE [END] - Request Number of Queues from Controller - - 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 (&CrIoCq, sizeof (NVME_ADMIN_CRIOCQ)); - - CommandPacket.NvmeCmd = &Command; - CommandPacket.NvmeCompletion = &Completion; - - Command.Cdw0.Opcode = NVME_ADMIN_CRIOCQ_CMD; - CommandPacket.TransferBuffer = Private->CqBufferPciAddr[Index]; - CommandPacket.TransferLength = EFI_PAGE_SIZE; - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket.QueueType = NVME_ADMIN_QUEUE; - - // MU_CHANGE [BEGIN] - Use the Mqes value from the Cap register - // MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - if (PcdGetBool (PcdSupportAlternativeQueueSize)) { - QueueSize = MIN (NVME_ALTERNATIVE_MAX_QUEUE_SIZE, Private->Cap.Mqes); - } else if (Index == 1) { - // MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - QueueSize = MIN (NVME_CCQ_SIZE, Private->Cap.Mqes); - } else { - QueueSize = MIN (NVME_ASYNC_CCQ_SIZE, Private->Cap.Mqes); - } - - // MU_CHANGE [END] - Use the Mqes value from the Cap register - - CrIoCq.Qid = Index; - CrIoCq.Qsize = QueueSize; - CrIoCq.Pc = 1; - CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoCq, sizeof (NVME_ADMIN_CRIOCQ)); - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - 0, - &CommandPacket, - NULL - ); - if (EFI_ERROR (Status)) { - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - DEBUG ((DEBUG_ERROR, "%a: Create Completion Queue Command %d failed with Status %r\n", __func__, Index, Status)); - // MU_CHANGE [END] - Request Number of Queues from Controller - break; - } - } - - Private->CreateIoQueue = FALSE; - - return Status; -} - -/** - Create io submission queue. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @return EFI_SUCCESS Successfully create io submission queue. - @return EFI_DEVICE_ERROR Fail to create io submission queue. - -**/ -EFI_STATUS -NvmeCreateIoSubmissionQueue ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET CommandPacket; - EFI_NVM_EXPRESS_COMMAND Command; - EFI_NVM_EXPRESS_COMPLETION Completion; - EFI_STATUS Status; - NVME_ADMIN_CRIOSQ CrIoSq; - UINT32 Index; - UINT16 QueueSize; - - Status = EFI_SUCCESS; - Private->CreateIoQueue = TRUE; - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - // Start from Index 1 because Index 0 is reserved for admin queue - for (Index = 1; Index <= Private->NumberOfIoQueuePairs; Index++) { - // MU_CHANGE [END] - Request Number of Queues from Controller - 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 (&CrIoSq, sizeof (NVME_ADMIN_CRIOSQ)); - - CommandPacket.NvmeCmd = &Command; - CommandPacket.NvmeCompletion = &Completion; - - Command.Cdw0.Opcode = NVME_ADMIN_CRIOSQ_CMD; - CommandPacket.TransferBuffer = Private->SqBufferPciAddr[Index]; - CommandPacket.TransferLength = EFI_PAGE_SIZE; - CommandPacket.CommandTimeout = NVME_GENERIC_TIMEOUT; - CommandPacket.QueueType = NVME_ADMIN_QUEUE; - - // MU_CHANGE [BEGIN] - Use the Mqes value from the Cap register - // MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - if (PcdGetBool (PcdSupportAlternativeQueueSize)) { - QueueSize = MIN (NVME_ALTERNATIVE_MAX_QUEUE_SIZE, Private->Cap.Mqes); - } else if (Index == 1) { - // MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - QueueSize = MIN (NVME_CSQ_SIZE, Private->Cap.Mqes); - } else { - QueueSize = MIN (NVME_ASYNC_CSQ_SIZE, Private->Cap.Mqes); - } - - // MU_CHANGE [END] - Use the Mqes value from the Cap register - - CrIoSq.Qid = Index; - CrIoSq.Qsize = QueueSize; - CrIoSq.Pc = 1; - CrIoSq.Cqid = Index; - CrIoSq.Qprio = 0; - CopyMem (&CommandPacket.NvmeCmd->Cdw10, &CrIoSq, sizeof (NVME_ADMIN_CRIOSQ)); - CommandPacket.NvmeCmd->Flags = CDW10_VALID | CDW11_VALID; - - Status = Private->Passthru.PassThru ( - &Private->Passthru, - 0, - &CommandPacket, - NULL - ); - if (EFI_ERROR (Status)) { - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - DEBUG ((DEBUG_ERROR, "%a: Create Submission Queue Command %d failed with Status %r\n", __func__, Index, Status)); - // MU_CHANGE [END] - Request Number of Queues from Controller - break; - } - } - - Private->CreateIoQueue = FALSE; - - return Status; -} - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Initialize the Nvm Express controller Data (IO) Queues - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS The NVM Express Controller IO Queues are initialized successfully. - @retval Others A device error occurred while initializing the IO Queues. - -**/ -EFI_STATUS -NvmeControllerInitIoQueues ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - UINTN SqPageCount; - UINTN IoQueuePairPageCount; - UINT32 Index; - EFI_STATUS Status; - - // Offset completion queue with submission queue size - SqPageCount = NVME_SQ_SIZE_IN_PAGES (Private, 1); - - // Calculate the number of pages required for the data queues - IoQueuePairPageCount = SqPageCount + NVME_CQ_SIZE_IN_PAGES (Private, 1); - - // - // Address of Data I/O submission & completion queue(s). - // We are using the same table of buffer pointers that the admin queues are in, so we start the table from Index + 1, but we have a separate - // buffer so we start at the beginning of that buffer. - // - ZeroMem (Private->IoQueueBuffer, EFI_PAGES_TO_SIZE (IoQueuePairPageCount) * Private->NumberOfIoQueuePairs); - for (Index = 0; Index < Private->NumberOfIoQueuePairs; Index++) { - Private->SqBuffer[Index + 1] = (NVME_SQ *)(UINTN)(Private->IoQueueBuffer + EFI_PAGES_TO_SIZE (Index * IoQueuePairPageCount)); - Private->SqBufferPciAddr[Index + 1] = (NVME_SQ *)(UINTN)(Private->IoQueueBufferPciAddr + EFI_PAGES_TO_SIZE (Index * IoQueuePairPageCount)); - Private->CqBuffer[Index + 1] = (NVME_CQ *)(UINTN)(Private->IoQueueBuffer + EFI_PAGES_TO_SIZE (Index * IoQueuePairPageCount + SqPageCount)); - Private->CqBufferPciAddr[Index + 1] = (NVME_CQ *)(UINTN)(Private->IoQueueBufferPciAddr + EFI_PAGES_TO_SIZE (Index * IoQueuePairPageCount + SqPageCount)); - - DEBUG ((DEBUG_INFO, "Data IO Submission Queue (SqBuffer[%d]) = [%016X]\n", Index + 1, Private->SqBuffer[Index + 1])); - DEBUG ((DEBUG_INFO, "Data IO Completion Queue (CqBuffer[%d]) = [%016X]\n", Index + 1, Private->CqBuffer[Index + 1])); - } - - // - // Create I/O completion queue(s). - // - Status = NvmeCreateIoCompletionQueue (Private); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Create I/O Submission queue(s). - // - Status = NvmeCreateIoSubmissionQueue (Private); - - return Status; -} - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Initialize the Nvm Express controller Admin Queues - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS The NVM Express Controller is initialized successfully. - @retval Others A device error occurred while initializing the controller. - -**/ -EFI_STATUS -NvmeControllerInitAdminQueues ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - NVME_ASQ Asq; - NVME_ACQ Acq; - UINTN AsqPageCount; - UINTN AsqSize; - UINTN AdminQueuePairPageCount; - EFI_STATUS Status; - - // Offset completion queue with submission queue size - AsqPageCount = NVME_SQ_SIZE_IN_PAGES (Private, 0); - AsqSize = EFI_PAGES_TO_SIZE (AsqPageCount); - - // - // Address of admin submission queue. - // - // MU_CHANGE - Remove Page Mask - Asq = (UINT64)(UINTN)(Private->BufferPciAddr); - - // - // Address of admin completion queue. - // - // MU_CHANGE - Remove Page Mask - Acq = (UINT64)(UINTN)(Private->BufferPciAddr + AsqSize); - - // Calculate the number of pages required for the admin queues - AdminQueuePairPageCount = AsqPageCount + NVME_CQ_SIZE_IN_PAGES (Private, 0); - - // - // Address of Admin I/O submission & completion queues. - // - ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (AdminQueuePairPageCount)); - Private->SqBuffer[0] = (NVME_SQ *)(UINTN)(Private->Buffer); - Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr); - Private->CqBuffer[0] = (NVME_CQ *)(UINTN)(Private->Buffer + AsqSize); - Private->CqBufferPciAddr[0] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + AsqSize); - - DEBUG ((DEBUG_INFO, "Private->Buffer = [%016X]\n", (UINT64)(UINTN)Private->Buffer)); - DEBUG ((DEBUG_INFO, "Admin Submission Queue size (Number of Entries) = [%08X]\n", Private->SqData[0].NumberOfEntries)); - DEBUG ((DEBUG_INFO, "Admin Completion Queue size (Number of Entries) = [%08X]\n", Private->CqData[0].NumberOfEntries)); - DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0])); - DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0])); - - // - // Program admin submission queue address. - // - Status = WriteNvmeAdminSubmissionQueueBaseAddress (Private, &Asq); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Program admin completion queue address. - // - Status = WriteNvmeAdminCompletionQueueBaseAddress (Private, &Acq); - - return Status; -} - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -/** - Initialize the Nvm Express controller. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS The NVM Express Controller is initialized successfully. - @retval Others A device error occurred while initializing the controller. - -**/ -EFI_STATUS -NvmeControllerInit ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT64 Supports; - UINT16 VidDid[2]; // MU_CHANGE - Improve NVMe controller init robustness - // NVME_ASQ Asq; - // NVME_ACQ Acq; - UINT8 Sn[21]; - UINT8 Mn[41]; - UINTN Bytes; - UINT32 Index; - EFI_PHYSICAL_ADDRESS MappedAddr; - NVME_AQA Aqa; - UINTN AdminQueuePairPageCount; - UINTN IoQueuePairPageCount; - - // MU_CHANGE [END] - Allocate IO Queue Buffer - - // MU_CHANGE [BEGIN] - Improve NVMe controller init robustness - PciIo = Private->PciIo; - - // - // Verify the controller is still accessible - // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint16, - PCI_VENDOR_ID_OFFSET, - ARRAY_SIZE (VidDid), - VidDid - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return EFI_DEVICE_ERROR; - } - - if ((VidDid[0] == NVME_INVALID_VID_DID) || (VidDid[1] == NVME_INVALID_VID_DID)) { - return EFI_DEVICE_ERROR; - } - - // MU_CHANGE [END] - Improve NVMe controller init robustness - - // - // Enable this controller. - // - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationSupported, - 0, - &Supports - ); - - if (!EFI_ERROR (Status)) { - Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE; - Status = PciIo->Attributes ( - PciIo, - EfiPciIoAttributeOperationEnable, - Supports, - NULL - ); - } - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "NvmeControllerInit: failed to enable controller\n")); - return Status; - } - - // - // Read the Controller Capabilities register and verify that the NVM command set is supported - // - Status = ReadNvmeControllerCapabilities (Private, &Private->Cap); - if (EFI_ERROR (Status)) { - return Status; - } - - if ((Private->Cap.Css & BIT0) == 0) { - DEBUG ((DEBUG_INFO, "NvmeControllerInit: the controller doesn't support NVMe command set\n")); - return EFI_UNSUPPORTED; - } - - // - // Currently the driver only supports 4k page size. - // - // MU_CHANGE [BEGIN] - Improve NVMe controller init robustness - - // Currently, this means Cap.Mpsmin must be zero for an EFI_PAGE_SHIFT size of 12. - // ASSERT ((Private->Cap.Mpsmin + 12) <= EFI_PAGE_SHIFT); - if ((Private->Cap.Mpsmin + 12) > EFI_PAGE_SHIFT) { - DEBUG ((DEBUG_ERROR, "NvmeControllerInit: Mpsmin is larger than expected (0x%02x).\n", Private->Cap.Mpsmin)); - return EFI_DEVICE_ERROR; - } - - // MU_CHANGE [END] - Improve NVMe controller init robustness - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - - // 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; - - for (Index = 0; Index < NVME_MAX_QUEUES; Index++) { - Private->Cid[Index] = 0; - Private->Pt[Index] = 0; - Private->SqTdbl[Index].Sqt = 0; - Private->CqHdbl[Index].Cqh = 0; - } - - Private->AsyncSqHead = 0; - - // - // set number of entries admin submission & completion queues. - // - // MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - Aqa.Asqs = PcdGetBool (PcdSupportAlternativeQueueSize) ? MIN (NVME_ALTERNATIVE_MAX_QUEUE_SIZE, Private->Cap.Mqes) : MIN (NVME_ASQ_SIZE, Private->Cap.Mqes); - Aqa.Rsvd1 = 0; - Aqa.Acqs = PcdGetBool (PcdSupportAlternativeQueueSize) ? MIN (NVME_ALTERNATIVE_MAX_QUEUE_SIZE, Private->Cap.Mqes) : MIN (NVME_ACQ_SIZE, Private->Cap.Mqes); - Aqa.Rsvd2 = 0; - // MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - - // - // Set admin queue entry size to default - // Note we are using the spec-defined minimum SQES and CQES here. - // - Private->SqData[0].EntrySize = NVME_IOSQES_MIN; - Private->SqData[0].NumberOfEntries = Aqa.Asqs; - Private->CqData[0].EntrySize = NVME_IOCQES_MIN; - Private->CqData[0].NumberOfEntries = Aqa.Acqs; - - // Calculate the number of pages required for the admin queues - AdminQueuePairPageCount = NVME_SQ_SIZE_IN_PAGES (Private, 0) + NVME_CQ_SIZE_IN_PAGES (Private, 0); - - // - // Default: - // 6 x 4kB aligned buffers will be carved out of this buffer. - // 1st 4kB boundary is the start of the admin submission queue. - // 2nd 4kB boundary is the start of the admin completion queue. - // 3rd 4kB boundary is the start of I/O submission queue #1. - // 4th 4kB boundary is the start of I/O completion queue #1. - // 5th 4kB boundary is the start of I/O submission queue #2. - // 6th 4kB boundary is the start of I/O completion queue #2. - // - // Allocate 6 pages of memory, then map it for bus master read and write. - // - Status = PciIo->AllocateBuffer ( - PciIo, - AllocateAnyPages, - EfiBootServicesData, - AdminQueuePairPageCount, - (VOID **)&Private->Buffer, - 0 - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) { - Status = NvmExpressMakeAddressRangeShared(&Private->QueueVisibilityContext, - Private->Buffer, - (UINT32)AdminQueuePairPageCount * EFI_PAGE_SIZE - ); - - if (EFI_ERROR (Status)) { - EFI_STATUS FreeStatus = PciIo->FreeBuffer (PciIo, AdminQueuePairPageCount, Private->Buffer); - - if (EFI_ERROR (FreeStatus)) { - DEBUG ((DEBUG_ERROR, "%a: FreeBuffer Admin Queue Buffer failed %r\n", __func__, FreeStatus)); - ASSERT_EFI_ERROR (FreeStatus); - } - - Private->Buffer = NULL; - return Status; - } - } - // MS_HYP_CHANGE END - - Bytes = EFI_PAGES_TO_SIZE (AdminQueuePairPageCount); - Status = PciIo->Map ( - PciIo, - EfiPciIoOperationBusMasterCommonBuffer, - Private->Buffer, - &Bytes, - &MappedAddr, - &Private->Mapping - ); - if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (AdminQueuePairPageCount))) { - return EFI_DEVICE_ERROR; - } - - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) { - // - // Canonicalize the VA. - // - Private->Buffer = NvmExpressGetSharedVa(Private->Buffer); - } - // MS_HYP_CHANGE END - - Private->BufferPciAddr = (UINT8 *)(UINTN)MappedAddr; - - // Disable the controller to wait for CSTS.RDY to become 0 - // NVMe Base Specification 2.0e, Section 3.5 Controller Initialization - // MU_CHANGE [END] - Allocate IO Queue Buffer - Status = NvmeDisableController (Private); - - if (EFI_ERROR (Status)) { - return Status; - } - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // - // Address of admin submission queue. - // - // MU_CHANGE - Remove the page mask since the buffer is allocated using AllocatePages - // Asq = (UINT64)(UINTN)(Private->BufferPciAddr); - - // - // Address of admin completion queue. - // - // MU_CHANGE - Remove the page mask since the buffer is allocated using AllocatePages - // Acq = (UINT64)(UINTN)(Private->BufferPciAddr + EFI_PAGE_SIZE); - - // - // Address of I/O submission & completion queue. - // - // ZeroMem (Private->Buffer, EFI_PAGES_TO_SIZE (6)); - // Private->SqBuffer[0] = (NVME_SQ *)(UINTN)(Private->Buffer); - // Private->SqBufferPciAddr[0] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr); - // Private->CqBuffer[0] = (NVME_CQ *)(UINTN)(Private->Buffer + 1 * EFI_PAGE_SIZE); - // Private->CqBufferPciAddr[0] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 1 * EFI_PAGE_SIZE); - // Private->SqBuffer[1] = (NVME_SQ *)(UINTN)(Private->Buffer + 2 * EFI_PAGE_SIZE); - // Private->SqBufferPciAddr[1] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 2 * EFI_PAGE_SIZE); - // Private->CqBuffer[1] = (NVME_CQ *)(UINTN)(Private->Buffer + 3 * EFI_PAGE_SIZE); - // Private->CqBufferPciAddr[1] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 3 * EFI_PAGE_SIZE); - // Private->SqBuffer[2] = (NVME_SQ *)(UINTN)(Private->Buffer + 4 * EFI_PAGE_SIZE); - // Private->SqBufferPciAddr[2] = (NVME_SQ *)(UINTN)(Private->BufferPciAddr + 4 * EFI_PAGE_SIZE); - // Private->CqBuffer[2] = (NVME_CQ *)(UINTN)(Private->Buffer + 5 * EFI_PAGE_SIZE); - // Private->CqBufferPciAddr[2] = (NVME_CQ *)(UINTN)(Private->BufferPciAddr + 5 * EFI_PAGE_SIZE); - - // DEBUG ((DEBUG_INFO, "Admin Submission Queue size (Aqa.Asqs) = [%08X]\n", Aqa.Asqs)); - // DEBUG ((DEBUG_INFO, "Admin Completion Queue size (Aqa.Acqs) = [%08X]\n", Aqa.Acqs)); - // DEBUG ((DEBUG_INFO, "Admin Submission Queue (SqBuffer[0]) = [%016X]\n", Private->SqBuffer[0])); - // DEBUG ((DEBUG_INFO, "Admin Completion Queue (CqBuffer[0]) = [%016X]\n", Private->CqBuffer[0])); - // DEBUG ((DEBUG_INFO, "Sync I/O Submission Queue (SqBuffer[1]) = [%016X]\n", Private->SqBuffer[1])); - // DEBUG ((DEBUG_INFO, "Sync I/O Completion Queue (CqBuffer[1]) = [%016X]\n", Private->CqBuffer[1])); - // DEBUG ((DEBUG_INFO, "Async I/O Submission Queue (SqBuffer[2]) = [%016X]\n", Private->SqBuffer[2])); - // DEBUG ((DEBUG_INFO, "Async I/O Completion Queue (CqBuffer[2]) = [%016X]\n", Private->CqBuffer[2])); - - // - // Program admin queue attributes. - // - Status = WriteNvmeAdminQueueAttributes (Private, &Aqa); - - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Program admin submission queue address. - // - // Status = WriteNvmeAdminSubmissionQueueBaseAddress (Private, &Asq); - - // - // Program admin completion queue address. - // - // Status = WriteNvmeAdminCompletionQueueBaseAddress (Private, &Acq); - - Status = NvmeControllerInitAdminQueues (Private); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = NvmeEnableController (Private, Private->SqData[0].EntrySize, Private->CqData[0].EntrySize); - if (EFI_ERROR (Status)) { - return Status; - } - - // MU_CHANGE [END] - Allocate IO Queue Buffer - - // - // Allocate buffer for Identify Controller data - // - if (Private->ControllerData == NULL) { - Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_CONTROLLER_DATA)); - - if (Private->ControllerData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } - - // - // Get current Identify Controller Data - // - Status = NvmeIdentifyController (Private, Private->ControllerData); - - if (EFI_ERROR (Status)) { - FreePool (Private->ControllerData); - Private->ControllerData = NULL; - return EFI_NOT_FOUND; - } - - // - // Dump NvmExpress Identify Controller Data - // - // Serial Number and Model Number are not null-terminated strings, but will be printed as ones. - // So here we add a null terminator to the end of their arrays. - CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn)); - Sn[20] = 0; - CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn)); - Mn[40] = 0; - DEBUG ((DEBUG_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n")); - DEBUG ((DEBUG_INFO, " PCI VID : 0x%x\n", Private->ControllerData->Vid)); - DEBUG ((DEBUG_INFO, " PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid)); - DEBUG ((DEBUG_INFO, " SN : %a\n", Sn)); - DEBUG ((DEBUG_INFO, " MN : %a\n", Mn)); - DEBUG ((DEBUG_INFO, " FR : 0x%x\n", *((UINT64 *)Private->ControllerData->Fr))); - DEBUG ((DEBUG_INFO, " TNVMCAP (high 8-byte) : 0x%lx\n", *((UINT64 *)(Private->ControllerData->Tnvmcap + 8)))); - DEBUG ((DEBUG_INFO, " TNVMCAP (low 8-byte) : 0x%lx\n", *((UINT64 *)Private->ControllerData->Tnvmcap))); - DEBUG ((DEBUG_INFO, " RAB : 0x%x\n", Private->ControllerData->Rab)); - DEBUG ((DEBUG_INFO, " IEEE : 0x%x\n", *(UINT32 *)Private->ControllerData->Ieee_oui)); - DEBUG ((DEBUG_INFO, " AERL : 0x%x\n", Private->ControllerData->Aerl)); - DEBUG ((DEBUG_INFO, " SQES : 0x%x\n", Private->ControllerData->Sqes)); - DEBUG ((DEBUG_INFO, " CQES : 0x%x\n", Private->ControllerData->Cqes)); - DEBUG ((DEBUG_INFO, " NN : 0x%x\n", Private->ControllerData->Nn)); - - // MU_CHANGE [BEGIN] - Request Number of Queues from Controller - // - // Send Set Features Command to request the maximum number of data queues. - // The controller is free to allocate a different number of queues from the number requested. - // The number of queues allocated is returned and stored in the controller private data structure - // using the NumberOfIoQueuePairs field. - // - Status = NvmeSetFeaturesNumberOfQueues (Private, NVME_MAX_QUEUES - 1); - - if (EFI_ERROR (Status)) { - return Status; - } - - // MU_CHANGE [END] - Request Number of Queues from Controller - - // MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - // - // Allocate Data Queues - note we are assuming the queue entry sizes are the same as the admin queue entry sizes for the sake of memory allocation. - // The identify controller data tells us in SQES and CQES what the controller's minimum and maximum queue entry sizes are. We haven't used this before since we - // use the spec-defined minimum queue entry sizes. - // We are also allocating based on the admin defined queue sizes in number of entries. - // Some scenarios may use different queue sizes, currently we only see the case where the driver needs IO queue sizes <= admin queue sizes. So this allocation should be sufficient. - // We may want to explore a more dynamic allocation in the future. - // - for (Index = 1; Index <= Private->NumberOfIoQueuePairs; Index++) { - Private->SqData[Index].NumberOfEntries = Private->SqData[0].NumberOfEntries; - Private->CqData[Index].NumberOfEntries = Private->CqData[0].NumberOfEntries; - Private->SqData[Index].EntrySize = Private->SqData[0].EntrySize; - Private->CqData[Index].EntrySize = Private->CqData[0].EntrySize; - } - - // Using the first data queue size for the number of pages required for the data queues - IoQueuePairPageCount = NVME_SQ_SIZE_IN_PAGES (Private, 1) + NVME_CQ_SIZE_IN_PAGES (Private, 1); - - Status = PciIo->AllocateBuffer ( - PciIo, - AllocateAnyPages, - EfiBootServicesData, - IoQueuePairPageCount * Private->NumberOfIoQueuePairs, - (VOID **)&Private->IoQueueBuffer, - 0 - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // MS_HYP_CHANGE BEGIN - if (IsIsolated ()) { - Status = NvmExpressMakeAddressRangeShared ( - &Private->IoQueueVisibilityContext, - Private->IoQueueBuffer, - (UINT32)IoQueuePairPageCount * Private->NumberOfIoQueuePairs * EFI_PAGE_SIZE - ); - - if (EFI_ERROR (Status)) { - EFI_STATUS FreeStatus = PciIo->FreeBuffer (PciIo, IoQueuePairPageCount*Private->NumberOfIoQueuePairs, Private->IoQueueBuffer); - - if (EFI_ERROR (FreeStatus)) { - DEBUG ((DEBUG_ERROR, "%a: FreeBuffer IoQueueBuffer failed %r\n", __func__, FreeStatus)); - ASSERT_EFI_ERROR (FreeStatus); - } - - Private->IoQueueBuffer = NULL; - return Status; - } - } - // MS_HYP_CHANGE END - - Bytes = EFI_PAGES_TO_SIZE (IoQueuePairPageCount * Private->NumberOfIoQueuePairs); - Status = PciIo->Map ( - PciIo, - EfiPciIoOperationBusMasterCommonBuffer, - Private->IoQueueBuffer, - &Bytes, - &MappedAddr, - &Private->IoQueueMapping - ); - - if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (IoQueuePairPageCount * Private->NumberOfIoQueuePairs))) { - return EFI_DEVICE_ERROR; - } - - - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) { - // - // Canonicalize the VA. - // - Private->IoQueueBuffer = NvmExpressGetSharedVa(Private->IoQueueBuffer); - } - // MS_HYP_CHANGE END - - - Private->IoQueueBufferPciAddr = (UINT8 *)(UINTN)MappedAddr; - - Status = NvmeControllerInitIoQueues (Private); - // MU_CHANGE [END] - Allocate IO Queue Buffer - - return Status; -} - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Reset the Nvm Express controller. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS The NVM Express Controller is reset successfully. - @retval Others A device error occurred while resetting the controller. - -**/ -EFI_STATUS -NvmeControllerReset ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - EFI_STATUS Status; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT32 Index; - UINT16 VidDid[2]; - UINT8 Sn[21]; - UINT8 Mn[41]; - NVME_AQA Aqa; - UINT32 NdqpBeforeReset; - - DEBUG ((DEBUG_INFO, "%a: Begin Controller Reset\n", __func__)); - - PciIo = Private->PciIo; - - // - // Verify the controller is still accessible - // - Status = PciIo->Pci.Read ( - PciIo, - EfiPciIoWidthUint16, - PCI_VENDOR_ID_OFFSET, - ARRAY_SIZE (VidDid), - VidDid - ); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return EFI_DEVICE_ERROR; - } - - if ((VidDid[0] == NVME_INVALID_VID_DID) || (VidDid[1] == NVME_INVALID_VID_DID)) { - return EFI_DEVICE_ERROR; - } - - for (Index = 0; Index < NVME_MAX_QUEUES; Index++) { - Private->Cid[Index] = 0; - Private->Pt[Index] = 0; - Private->SqTdbl[Index].Sqt = 0; - Private->CqHdbl[Index].Cqh = 0; - } - - Private->AsyncSqHead = 0; - - Status = NvmeDisableController (Private); - - if (EFI_ERROR (Status)) { - return Status; - } - - Status = ReadNvmeAdminQueueAttributes (Private, &Aqa); - if (EFI_ERROR (Status)) { - return Status; - } - - if ((Private->SqData[0].NumberOfEntries != Aqa.Asqs) || (Private->CqData[0].NumberOfEntries != Aqa.Acqs)) { - // By spec these values should not change between resets, so we'll fail out here. - DEBUG ((DEBUG_ERROR, "%a: Admin Submission Queue Size (Number of Entries) mismatch: %d != %d\n", __func__, Private->SqData[0].NumberOfEntries, Aqa.Asqs)); - ASSERT (FALSE); - return EFI_DEVICE_ERROR; - } - - Status = NvmeControllerInitAdminQueues (Private); - - if (EFI_ERROR (Status)) { - return Status; - } - - Status = NvmeEnableController (Private, Private->SqData[0].EntrySize, Private->CqData[0].EntrySize); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Allocate buffer for Identify Controller data - // - if (Private->ControllerData == NULL) { - Private->ControllerData = (NVME_ADMIN_CONTROLLER_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_CONTROLLER_DATA)); - - if (Private->ControllerData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } - - // - // Get current Identify Controller Data - // - Status = NvmeIdentifyController (Private, Private->ControllerData); - - if (EFI_ERROR (Status)) { - FreePool (Private->ControllerData); - Private->ControllerData = NULL; - return EFI_NOT_FOUND; - } - - // - // Dump NvmExpress Identify Controller Data - // - CopyMem (Sn, Private->ControllerData->Sn, sizeof (Private->ControllerData->Sn)); - // Serial Number and Model Number are not null-terminated strings, but will be printed as ones. - // So here we add a null terminator to the end of their arrays. - Sn[20] = 0; - CopyMem (Mn, Private->ControllerData->Mn, sizeof (Private->ControllerData->Mn)); - Mn[40] = 0; - DEBUG ((DEBUG_INFO, " == NVME IDENTIFY CONTROLLER DATA ==\n")); - DEBUG ((DEBUG_INFO, " PCI VID : 0x%x\n", Private->ControllerData->Vid)); - DEBUG ((DEBUG_INFO, " PCI SSVID : 0x%x\n", Private->ControllerData->Ssvid)); - DEBUG ((DEBUG_INFO, " SN : %a\n", Sn)); - DEBUG ((DEBUG_INFO, " MN : %a\n", Mn)); - DEBUG ((DEBUG_INFO, " FR : 0x%x\n", *((UINT64 *)Private->ControllerData->Fr))); - DEBUG ((DEBUG_INFO, " TNVMCAP (high 8-byte) : 0x%lx\n", *((UINT64 *)(Private->ControllerData->Tnvmcap + 8)))); - DEBUG ((DEBUG_INFO, " TNVMCAP (low 8-byte) : 0x%lx\n", *((UINT64 *)Private->ControllerData->Tnvmcap))); - DEBUG ((DEBUG_INFO, " RAB : 0x%x\n", Private->ControllerData->Rab)); - DEBUG ((DEBUG_INFO, " IEEE : 0x%x\n", *(UINT32 *)Private->ControllerData->Ieee_oui)); - DEBUG ((DEBUG_INFO, " AERL : 0x%x\n", Private->ControllerData->Aerl)); - DEBUG ((DEBUG_INFO, " SQES : 0x%x\n", Private->ControllerData->Sqes)); - DEBUG ((DEBUG_INFO, " CQES : 0x%x\n", Private->ControllerData->Cqes)); - DEBUG ((DEBUG_INFO, " NN : 0x%x\n", Private->ControllerData->Nn)); - - // - // Send Set Features Command to request the maximum number of data queues. - // The controller is free to allocate a different number of queues from the number requested. - // The number of queues allocated is returned and stored in the controller private data structure - // using the NumberOfIoQueuePairs field. - // - NdqpBeforeReset = Private->NumberOfIoQueuePairs; - Status = NvmeSetFeaturesNumberOfQueues (Private, NVME_MAX_QUEUES - 1); - if (EFI_ERROR (Status)) { - return Status; - } - - if (NdqpBeforeReset != Private->NumberOfIoQueuePairs) { - // This is a controller reset, so the number of data queues should not have changed. - // If the number of queues has changed, then the driver must be re-initialized. - DEBUG ((DEBUG_ERROR, "%a: Number of Data Queue Pairs mismatch: %d != %d\n", __func__, NdqpBeforeReset, Private->NumberOfIoQueuePairs)); - ASSERT (FALSE); - return EFI_DEVICE_ERROR; - } - - // - // Create I/O completion queue(s). - // - Status = NvmeControllerInitIoQueues (Private); - if (EFI_ERROR (Status)) { - return Status; - } - - return Status; -} - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -/** - This routine is called to properly shutdown the Nvm Express controller per NVMe spec. - - @param[in] ResetType The type of reset to perform. - @param[in] ResetStatus The status code for the reset. - @param[in] DataSize The size, in bytes, of ResetData. - @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or - EfiResetShutdown the data buffer starts with a Null-terminated - string, optionally followed by additional binary data. - The string is a description that the caller may use to further - indicate the reason for the system reset. - For a ResetType of EfiResetPlatformSpecific the data buffer - also starts with a Null-terminated string that is followed - by an EFI_GUID that describes the specific type of reset to perform. -**/ -VOID -EFIAPI -NvmeShutdownAllControllers ( - IN EFI_RESET_TYPE ResetType, - IN EFI_STATUS ResetStatus, - IN UINTN DataSize, - IN VOID *ResetData OPTIONAL - ) -{ - EFI_STATUS Status; - EFI_HANDLE *Handles; - UINTN HandleCount; - UINTN HandleIndex; - EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfos; - UINTN OpenInfoCount; - UINTN OpenInfoIndex; - EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *NvmePassThru; - NVME_CC Cc; - NVME_CSTS Csts; - UINTN Index; - NVME_CONTROLLER_PRIVATE_DATA *Private; - - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleCount, - &Handles - ); - if (EFI_ERROR (Status)) { - HandleCount = 0; - } - - for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { - Status = gBS->OpenProtocolInformation ( - Handles[HandleIndex], - &gEfiPciIoProtocolGuid, - &OpenInfos, - &OpenInfoCount - ); - if (EFI_ERROR (Status)) { - continue; - } - - for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { - // - // Find all the NVME controller managed by this driver. - // gImageHandle equals to DriverBinding handle for this driver. - // - if (((OpenInfos[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) && - (OpenInfos[OpenInfoIndex].AgentHandle == gImageHandle)) - { - Status = gBS->OpenProtocol ( - OpenInfos[OpenInfoIndex].ControllerHandle, - &gEfiNvmExpressPassThruProtocolGuid, - (VOID **)&NvmePassThru, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - continue; - } - - Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (NvmePassThru); - - // - // Read Controller Configuration Register. - // - Status = ReadNvmeControllerConfiguration (Private, &Cc); - if (EFI_ERROR (Status)) { - continue; - } - - // - // The host should set the Shutdown Notification (CC.SHN) field to 01b - // to indicate a normal shutdown operation. - // - Cc.Shn = NVME_CC_SHN_NORMAL_SHUTDOWN; - Status = WriteNvmeControllerConfiguration (Private, &Cc); - if (EFI_ERROR (Status)) { - continue; - } - - // - // The controller indicates when shutdown processing is completed by updating the - // Shutdown Status (CSTS.SHST) field to 10b. - // Wait up to 45 seconds (break down to 4500 x 10ms) for the shutdown to complete. - // - for (Index = 0; Index < NVME_SHUTDOWN_PROCESS_TIMEOUT * 100; Index++) { - Status = ReadNvmeControllerStatus (Private, &Csts); - if (!EFI_ERROR (Status) && (Csts.Shst == NVME_CSTS_SHST_SHUTDOWN_COMPLETED)) { - DEBUG ((DEBUG_INFO, "NvmeShutdownController: shutdown processing is completed after %dms.\n", Index * 10)); - break; - } - - // - // Stall for 10ms - // - gBS->Stall (10 * 1000); - } - - if (Index == NVME_SHUTDOWN_PROCESS_TIMEOUT * 100) { - DEBUG ((DEBUG_ERROR, "NvmeShutdownController: shutdown processing is timed out\n")); - } - } - } - } -} - -/** - Register the shutdown notification through the ResetNotification protocol. - - Register the shutdown notification when mNvmeControllerNumber increased from 0 to 1. -**/ -VOID -NvmeRegisterShutdownNotification ( - VOID - ) -{ - EFI_STATUS Status; - EFI_RESET_NOTIFICATION_PROTOCOL *ResetNotify; - - mNvmeControllerNumber++; - if (mNvmeControllerNumber == 1) { - Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **)&ResetNotify); - if (!EFI_ERROR (Status)) { - Status = ResetNotify->RegisterResetNotify (ResetNotify, NvmeShutdownAllControllers); - ASSERT_EFI_ERROR (Status); - } else { - DEBUG ((DEBUG_WARN, "NVME: ResetNotification absent! Shutdown notification cannot be performed!\n")); - } - } -} - -/** - Unregister the shutdown notification through the ResetNotification protocol. - - Unregister the shutdown notification when mNvmeControllerNumber decreased from 1 to 0. -**/ -VOID -NvmeUnregisterShutdownNotification ( - VOID - ) -{ - EFI_STATUS Status; - EFI_RESET_NOTIFICATION_PROTOCOL *ResetNotify; - - mNvmeControllerNumber--; - if (mNvmeControllerNumber == 0) { - Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **)&ResetNotify); - if (!EFI_ERROR (Status)) { - Status = ResetNotify->UnregisterResetNotify (ResetNotify, NvmeShutdownAllControllers); - ASSERT_EFI_ERROR (Status); - } - } -} diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressHci.h b/MsvmPkg/NvmExpressDxe/NvmExpressHci.h deleted file mode 100644 index 4027616e6..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressHci.h +++ /dev/null @@ -1,107 +0,0 @@ -/** @file - NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows - NVM Express specification. - - (C) Copyright 2016 Hewlett Packard Enterprise Development LP
- Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef _NVME_HCI_H_ -#define _NVME_HCI_H_ - -#define NVME_BAR 0 - -// -// Offset from the beginning of private data queue buffer -// -#define NVME_ASQ_BUF_OFFSET EFI_PAGE_SIZE - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Reset the Nvm Express controller. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS The NVM Express Controller is reset successfully. - @retval Others A device error occurred while resetting the controller. - -**/ -EFI_STATUS -NvmeControllerReset ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ); - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -/** - Initialize the Nvm Express controller. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - - @retval EFI_SUCCESS The NVM Express Controller is initialized successfully. - @retval Others A device error occurred while initializing the controller. - -**/ -EFI_STATUS -NvmeControllerInit ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ); - -/** - Get identify controller data. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Buffer The buffer used to store the identify controller data. - - @return EFI_SUCCESS Successfully get the identify controller data. - @return EFI_DEVICE_ERROR Fail to get the identify controller data. - -**/ -EFI_STATUS -NvmeIdentifyController ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN VOID *Buffer - ); - -/** - Get specified identify namespace data. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param NamespaceId The specified namespace identifier. - @param Buffer The buffer used to store the identify namespace data. - - @return EFI_SUCCESS Successfully get the identify namespace data. - @return EFI_DEVICE_ERROR Fail to get the identify namespace data. - -**/ -EFI_STATUS -NvmeIdentifyNamespace ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - IN UINT32 NamespaceId, - IN VOID *Buffer - ); - -// MU_CHANGE [BEGIN] - Allocate IO Queue Buffer - -/** - Read Nvm Express admin queue attributes register. - - @param Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure. - @param Aqa The buffer used to store the content to be read from admin queue attributes register. - - @return EFI_SUCCESS Successfully read data from the admin queue attributes register. - @return EFI_DEVICE_ERROR Fail to read data from the admin queue attributes register. - -**/ -EFI_STATUS -ReadNvmeAdminQueueAttributes ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private, - OUT NVME_AQA *Aqa - ); - -// MU_CHANGE [END] - Allocate IO Queue Buffer - -#endif diff --git a/MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.c b/MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.c deleted file mode 100644 index dd24c2c33..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.c +++ /dev/null @@ -1,584 +0,0 @@ -/** @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.
- 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/MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.h b/MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.h deleted file mode 100644 index 197b92397..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressMediaSanitize.h +++ /dev/null @@ -1,191 +0,0 @@ -/** @file - Header file for MEDIA_SANITIZE_PROTOCOL interface. - - Copyright (c) Microsoft Corporation.
- 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/MsvmPkg/NvmExpressDxe/NvmExpressPassthru.c b/MsvmPkg/NvmExpressDxe/NvmExpressPassthru.c deleted file mode 100644 index 207de8dc9..000000000 --- a/MsvmPkg/NvmExpressDxe/NvmExpressPassthru.c +++ /dev/null @@ -1,1470 +0,0 @@ -/** @file - NvmExpressDxe driver is used to manage non-volatile memory subsystem which follows - NVM Express specification. - - (C) Copyright 2014 Hewlett-Packard Development Company, L.P.
- Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include "NvmExpress.h" - -/** - Dump the execution status from a given completion queue entry. - - @param[in] Cq A pointer to the NVME_CQ item. - -**/ -VOID -NvmeDumpStatus ( - IN NVME_CQ *Cq - ) -{ - DEBUG ((DEBUG_VERBOSE, "Dump NVMe Completion Entry Status from [0x%x]:\n", Cq)); - - DEBUG ((DEBUG_VERBOSE, " SQ Identifier : [0x%x], Phase Tag : [%d], Cmd Identifier : [0x%x]\n", Cq->Sqid, Cq->Pt, Cq->Cid)); - - DEBUG ((DEBUG_VERBOSE, " NVMe Cmd Execution Result - ")); - - switch (Cq->Sct) { - case 0x0: - switch (Cq->Sc) { - case 0x0: - DEBUG ((DEBUG_VERBOSE, "Successful Completion\n")); - break; - case 0x1: - DEBUG ((DEBUG_VERBOSE, "Invalid Command Opcode\n")); - break; - case 0x2: - DEBUG ((DEBUG_VERBOSE, "Invalid Field in Command\n")); - break; - case 0x3: - DEBUG ((DEBUG_VERBOSE, "Command ID Conflict\n")); - break; - case 0x4: - DEBUG ((DEBUG_VERBOSE, "Data Transfer Error\n")); - break; - case 0x5: - DEBUG ((DEBUG_VERBOSE, "Commands Aborted due to Power Loss Notification\n")); - break; - case 0x6: - DEBUG ((DEBUG_VERBOSE, "Internal Device Error\n")); - break; - case 0x7: - DEBUG ((DEBUG_VERBOSE, "Command Abort Requested\n")); - break; - case 0x8: - DEBUG ((DEBUG_VERBOSE, "Command Aborted due to SQ Deletion\n")); - break; - case 0x9: - DEBUG ((DEBUG_VERBOSE, "Command Aborted due to Failed Fused Command\n")); - break; - case 0xA: - DEBUG ((DEBUG_VERBOSE, "Command Aborted due to Missing Fused Command\n")); - break; - case 0xB: - DEBUG ((DEBUG_VERBOSE, "Invalid Namespace or Format\n")); - break; - case 0xC: - DEBUG ((DEBUG_VERBOSE, "Command Sequence Error\n")); - break; - case 0xD: - DEBUG ((DEBUG_VERBOSE, "Invalid SGL Last Segment Descriptor\n")); - break; - case 0xE: - DEBUG ((DEBUG_VERBOSE, "Invalid Number of SGL Descriptors\n")); - break; - case 0xF: - DEBUG ((DEBUG_VERBOSE, "Data SGL Length Invalid\n")); - break; - case 0x10: - DEBUG ((DEBUG_VERBOSE, "Metadata SGL Length Invalid\n")); - break; - case 0x11: - DEBUG ((DEBUG_VERBOSE, "SGL Descriptor Type Invalid\n")); - break; - case 0x80: - DEBUG ((DEBUG_VERBOSE, "LBA Out of Range\n")); - break; - case 0x81: - DEBUG ((DEBUG_VERBOSE, "Capacity Exceeded\n")); - break; - case 0x82: - DEBUG ((DEBUG_VERBOSE, "Namespace Not Ready\n")); - break; - case 0x83: - DEBUG ((DEBUG_VERBOSE, "Reservation Conflict\n")); - break; - } - - break; - - case 0x1: - switch (Cq->Sc) { - case 0x0: - DEBUG ((DEBUG_VERBOSE, "Completion Queue Invalid\n")); - break; - case 0x1: - DEBUG ((DEBUG_VERBOSE, "Invalid Queue Identifier\n")); - break; - case 0x2: - DEBUG ((DEBUG_VERBOSE, "Maximum Queue Size Exceeded\n")); - break; - case 0x3: - DEBUG ((DEBUG_VERBOSE, "Abort Command Limit Exceeded\n")); - break; - case 0x5: - DEBUG ((DEBUG_VERBOSE, "Asynchronous Event Request Limit Exceeded\n")); - break; - case 0x6: - DEBUG ((DEBUG_VERBOSE, "Invalid Firmware Slot\n")); - break; - case 0x7: - DEBUG ((DEBUG_VERBOSE, "Invalid Firmware Image\n")); - break; - case 0x8: - DEBUG ((DEBUG_VERBOSE, "Invalid Interrupt Vector\n")); - break; - case 0x9: - DEBUG ((DEBUG_VERBOSE, "Invalid Log Page\n")); - break; - case 0xA: - DEBUG ((DEBUG_VERBOSE, "Invalid Format\n")); - break; - case 0xB: - DEBUG ((DEBUG_VERBOSE, "Firmware Application Requires Conventional Reset\n")); - break; - case 0xC: - DEBUG ((DEBUG_VERBOSE, "Invalid Queue Deletion\n")); - break; - case 0xD: - DEBUG ((DEBUG_VERBOSE, "Feature Identifier Not Saveable\n")); - break; - case 0xE: - DEBUG ((DEBUG_VERBOSE, "Feature Not Changeable\n")); - break; - case 0xF: - DEBUG ((DEBUG_VERBOSE, "Feature Not Namespace Specific\n")); - break; - case 0x10: - DEBUG ((DEBUG_VERBOSE, "Firmware Application Requires NVM Subsystem Reset\n")); - break; - case 0x80: - DEBUG ((DEBUG_VERBOSE, "Conflicting Attributes\n")); - break; - case 0x81: - DEBUG ((DEBUG_VERBOSE, "Invalid Protection Information\n")); - break; - case 0x82: - DEBUG ((DEBUG_VERBOSE, "Attempted Write to Read Only Range\n")); - break; - } - - break; - - case 0x2: - switch (Cq->Sc) { - case 0x80: - DEBUG ((DEBUG_VERBOSE, "Write Fault\n")); - break; - case 0x81: - DEBUG ((DEBUG_VERBOSE, "Unrecovered Read Error\n")); - break; - case 0x82: - DEBUG ((DEBUG_VERBOSE, "End-to-end Guard Check Error\n")); - break; - case 0x83: - DEBUG ((DEBUG_VERBOSE, "End-to-end Application Tag Check Error\n")); - break; - case 0x84: - DEBUG ((DEBUG_VERBOSE, "End-to-end Reference Tag Check Error\n")); - break; - case 0x85: - DEBUG ((DEBUG_VERBOSE, "Compare Failure\n")); - break; - case 0x86: - DEBUG ((DEBUG_VERBOSE, "Access Denied\n")); - break; - } - - break; - - default: - break; - } -} - -/** - Create PRP lists for data transfer which is larger than 2 memory pages. - Note here we calcuate the number of required PRP lists and allocate them at one time. - - @param[in] PciIo A pointer to the EFI_PCI_IO_PROTOCOL instance. - @param[in] PhysicalAddr The physical base address of data buffer. - @param[in] Pages The number of pages to be transfered. - @param[in] BouncePageListHead A pointer to PNVME_BOUNCE_PAGE list. - @param[out] PrpListHost The host base address of PRP lists. - @param[in,out] PrpListNo The number of PRP List. - @param[out] Mapping The mapping value returned from PciIo.Map(). - @param[out] ProtectionHandle Object used to track memory range. - - @retval The pointer to the first PRP List of the PRP lists. - -**/ -VOID * -NvmeCreatePrpList ( - IN EFI_PCI_IO_PROTOCOL *PciIo, - IN EFI_PHYSICAL_ADDRESS PhysicalAddr, - IN UINTN Pages, - IN PNVME_BOUNCE_PAGE BouncePageListHead, // MS_HYP_CHANGE - OUT VOID **PrpListHost, - IN OUT UINTN *PrpListNo, - OUT VOID **Mapping, - IN OUT NVME_HOST_VISIBILITY_CONTEXT *HostVisibilityContext // MS_HYP_CHANGE - ) -{ - UINT64 PrpEntryNo; // MU_CHANGE - CodeQl Change - comparison mismatch - UINT64 PrpListBase; - UINT64 PrpListIndex; // MU_CHANGE - CodeQl Change - comparison mismatch - UINT64 PrpEntryIndex; // MU_CHANGE - CodeQl Change - comparison mismatch - UINT64 Remainder; - EFI_PHYSICAL_ADDRESS PrpListPhyAddr; - UINTN Bytes; - EFI_STATUS Status; - // MS_HYP_CHANGE BEGIN - PNVME_BOUNCE_PAGE BouncePage; - - ASSERT ((NvmExpressIsBounceActive() && (BouncePageListHead != NULL)) || - (!NvmExpressIsBounceActive() && (BouncePageListHead == NULL))); - // MS_HYP_CHANGE END - - // - // The number of Prp Entry in a memory page. - // - PrpEntryNo = EFI_PAGE_SIZE / sizeof (UINT64); - - // - // Calculate total PrpList number. - // - *PrpListNo = (UINTN)DivU64x64Remainder ((UINT64)Pages, (UINT64)PrpEntryNo - 1, &Remainder); - if (*PrpListNo == 0) { - *PrpListNo = 1; - } else if ((Remainder != 0) && (Remainder != 1)) { - *PrpListNo += 1; - } else if (Remainder == 1) { - Remainder = PrpEntryNo; - } else if (Remainder == 0) { - Remainder = PrpEntryNo - 1; - } - - Status = PciIo->AllocateBuffer ( - PciIo, - AllocateAnyPages, - EfiBootServicesData, - *PrpListNo, - PrpListHost, - 0 - ); - - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "%a: allocate PrpList failed %r\n", __func__, Status)); - return NULL; - } - - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) - { - Status = NvmExpressMakeAddressRangeShared(HostVisibilityContext, - *PrpListHost, - (UINT32)*PrpListNo * EFI_PAGE_SIZE); - - if (EFI_ERROR(Status)) - { - DEBUG ((DEBUG_ERROR, "%a: share PrpList failed %r\n", __func__, Status)); - PciIo->FreeBuffer (PciIo, *PrpListNo, *PrpListHost); - *PrpListHost = NULL; - goto EXIT; - } - } - // MS_HYP_CHANGE END - - Bytes = EFI_PAGES_TO_SIZE (*PrpListNo); - Status = PciIo->Map ( - PciIo, - EfiPciIoOperationBusMasterCommonBuffer, - *PrpListHost, - &Bytes, - &PrpListPhyAddr, - Mapping - ); - - if (EFI_ERROR (Status) || (Bytes != EFI_PAGES_TO_SIZE (*PrpListNo))) { - DEBUG ((DEBUG_ERROR, "%a: map PrpList failed %r\n", __func__, Status)); - goto EXIT; - } - - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) { - // - // Canonicalize the VA. - // - *PrpListHost = NvmExpressGetSharedVa(*PrpListHost); - } - // MS_HYP_CHANGE END - - // - // Fill all PRP lists except of last one. - // - - BouncePage = BouncePageListHead; // MS_HYP_CHANGE - - ZeroMem (*PrpListHost, Bytes); - for (PrpListIndex = 0; PrpListIndex < *PrpListNo - 1; ++PrpListIndex) { - PrpListBase = *(UINT64 *)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; - - for (PrpEntryIndex = 0; PrpEntryIndex < PrpEntryNo; ++PrpEntryIndex) { - if (PrpEntryIndex != PrpEntryNo - 1) { - // - // Fill all PRP entries except of last one. - // - // MS_HYP_CHANGE BEGIN - if (BouncePageListHead != NULL) { - ASSERT (BouncePage != NULL); - *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = BouncePage->HostVisiblePA; - BouncePage = BouncePage->NextBouncePage; - - } else { - // MS_HYP_CHANGE END - *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr; - PhysicalAddr += EFI_PAGE_SIZE; - } // MS_HYP_CHANGE - } else { - // - // Fill last PRP entries with next PRP List pointer. - // - *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = PrpListPhyAddr + (PrpListIndex + 1) * EFI_PAGE_SIZE; - } - } - } - - // - // Fill last PRP list. - // - PrpListBase = *(UINT64 *)PrpListHost + PrpListIndex * EFI_PAGE_SIZE; - for (PrpEntryIndex = 0; PrpEntryIndex < Remainder; ++PrpEntryIndex) { - - // MS_HYP_CHANGE BEGIN - if (BouncePageListHead != NULL) { - ASSERT (BouncePage != NULL); - *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = BouncePage->HostVisiblePA; - BouncePage = BouncePage->NextBouncePage; - - } else { - // MS_HYP_CHANGE END - *((UINT64 *)(UINTN)PrpListBase + PrpEntryIndex) = PhysicalAddr; - PhysicalAddr += EFI_PAGE_SIZE; - } // MS_HYP_CHANGE - } - - return (VOID *)(UINTN)PrpListPhyAddr; - -EXIT: - return NULL; -} - -/** - Aborts the asynchronous PassThru requests. - - @param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA - data structure. - - @retval EFI_SUCCESS The asynchronous PassThru requests have been aborted. - @return EFI_DEVICE_ERROR Fail to abort all the asynchronous PassThru requests. - -**/ -EFI_STATUS -AbortAsyncPassThruTasks ( - IN NVME_CONTROLLER_PRIVATE_DATA *Private - ) -{ - EFI_PCI_IO_PROTOCOL *PciIo; - LIST_ENTRY *Link; - LIST_ENTRY *NextLink; - NVME_BLKIO2_SUBTASK *Subtask; - NVME_BLKIO2_REQUEST *BlkIo2Request; - NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; - EFI_BLOCK_IO2_TOKEN *Token; - EFI_TPL OldTpl; - EFI_STATUS Status; - - PciIo = Private->PciIo; - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - - // - // Cancel the unsubmitted subtasks. - // - for (Link = GetFirstNode (&Private->UnsubmittedSubtasks); - !IsNull (&Private->UnsubmittedSubtasks, Link); - Link = NextLink) - { - NextLink = GetNextNode (&Private->UnsubmittedSubtasks, Link); - Subtask = NVME_BLKIO2_SUBTASK_FROM_LINK (Link); - BlkIo2Request = Subtask->BlockIo2Request; - Token = BlkIo2Request->Token; - - BlkIo2Request->UnsubmittedSubtaskNum--; - if (Subtask->IsLast) { - BlkIo2Request->LastSubtaskSubmitted = TRUE; - } - - Token->TransactionStatus = EFI_ABORTED; - - RemoveEntryList (Link); - InsertTailList (&BlkIo2Request->SubtasksQueue, Link); - gBS->SignalEvent (Subtask->Event); - } - - // - // Cleanup the resources for the asynchronous PassThru requests. - // - for (Link = GetFirstNode (&Private->AsyncPassThruQueue); - !IsNull (&Private->AsyncPassThruQueue, Link); - Link = NextLink) - { - NextLink = GetNextNode (&Private->AsyncPassThruQueue, Link); - AsyncRequest = NVME_PASS_THRU_ASYNC_REQ_FROM_THIS (Link); - - // MS_HYP_CHANGE BEGIN - if (AsyncRequest->TransferBouncePageList != NULL) { - NvmExpressReleaseBouncePages (Private, - AsyncRequest->TransferBouncePageList); - } - - if (AsyncRequest->MetadataBouncePageList != NULL) { - NvmExpressReleaseBouncePages (Private, - AsyncRequest->MetadataBouncePageList); - } - // MS_HYP_CHANGE END - - if (AsyncRequest->MapData != NULL) { - PciIo->Unmap (PciIo, AsyncRequest->MapData); - } - - if (AsyncRequest->MapMeta != NULL) { - PciIo->Unmap (PciIo, AsyncRequest->MapMeta); - } - - if (AsyncRequest->MapPrpList != NULL) { - PciIo->Unmap (PciIo, AsyncRequest->MapPrpList); - } - - if (AsyncRequest->PrpListHost != NULL) { - - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) { - NvmExpressMakeAddressRangePrivate(&AsyncRequest->PrpListHostVisibilityContext, AsyncRequest->PrpListHost); - } - // MS_HYP_CHANGE END - - PciIo->FreeBuffer ( - PciIo, - AsyncRequest->PrpListNo, - AsyncRequest->PrpListHost - ); - } - - RemoveEntryList (Link); - gBS->SignalEvent (AsyncRequest->CallerEvent); - FreePool (AsyncRequest); - } - - if (IsListEmpty (&Private->AsyncPassThruQueue) && - IsListEmpty (&Private->UnsubmittedSubtasks)) - { - Status = EFI_SUCCESS; - } else { - Status = EFI_DEVICE_ERROR; - } - - gBS->RestoreTPL (OldTpl); - - return Status; -} - -/** - Sends an NVM Express Command Packet to an NVM Express controller or namespace. This function supports - both blocking I/O and non-blocking I/O. The blocking I/O functionality is required, and the non-blocking - I/O functionality is optional. - - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @param[in] NamespaceId A 32 bit namespace ID as defined in the NVMe specification to which the NVM Express Command - Packet will be sent. A value of 0 denotes the NVM Express controller, a value of all 0xFF's - (all bytes are 0xFF) in the namespace ID specifies that the command packet should be sent to - all valid namespaces. - @param[in,out] Packet A pointer to the NVM Express Command Packet. - @param[in] Event If non-blocking I/O is not supported then Event is ignored, and blocking I/O is performed. - If Event is NULL, then blocking I/O is performed. If Event is not NULL and non-blocking I/O - is supported, then non-blocking I/O is performed, and Event will be signaled when the NVM - Express Command Packet completes. - - @retval EFI_SUCCESS The NVM Express Command Packet was sent by the host. TransferLength bytes were transferred - to, or from DataBuffer. - @retval EFI_BAD_BUFFER_SIZE The NVM Express Command Packet was not executed. The number of bytes that could be transferred - is returned in TransferLength. - @retval EFI_NOT_READY The NVM Express Command Packet could not be sent because the controller is not ready. The caller - may retry again later. - @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the NVM Express Command Packet. - @retval EFI_INVALID_PARAMETER NamespaceId or the contents of EFI_NVM_EXPRESS_PASS_THRU_COMMAND_PACKET are invalid. The NVM - Express Command Packet was not sent, so no additional status information is available. - @retval EFI_UNSUPPORTED The command described by the NVM Express Command Packet is not supported by the NVM Express - controller. The NVM Express Command Packet was not sent so no additional status information - is available. - @retval EFI_TIMEOUT A timeout occurred while waiting for the NVM Express Command Packet to execute. - -**/ -EFI_STATUS -EFIAPI -NvmExpressPassThru ( - 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 - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - EFI_STATUS Status; - EFI_STATUS PreviousStatus; - EFI_PCI_IO_PROTOCOL *PciIo; - NVME_SQ *Sq; - volatile NVME_CQ *Cq; - UINT16 QueueId; - UINT16 QueueSize; - UINT32 Bytes; - UINT16 Offset; - EFI_EVENT TimerEvent; - EFI_PCI_IO_PROTOCOL_OPERATION Flag; - EFI_PHYSICAL_ADDRESS PhyAddr; - VOID *MapData; - VOID *MapMeta; - VOID *MapPrpList; - UINTN MapLength; - UINT64 *Prp; - VOID *PrpListHost; - UINTN PrpListNo; - UINT32 Attributes; - UINT32 IoAlign; - UINT32 MaxTransLen; - UINT32 Data; - NVME_PASS_THRU_ASYNC_REQ *AsyncRequest; - EFI_TPL OldTpl; - // MS_HYP_CHANGE BEGIN - UINT32 BouncePageCount; - NVME_HOST_VISIBILITY_CONTEXT PrpListVisibilityContext; - PNVME_BOUNCE_PAGE TransferBouncePageList; - PNVME_BOUNCE_PAGE MetadataBouncePageList; - // MS_HYP_CHANGE END - - // - // check the data fields in Packet parameter. - // - if ((This == NULL) || (Packet == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if ((Packet->NvmeCmd == NULL) || (Packet->NvmeCompletion == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if ((Packet->QueueType != NVME_ADMIN_QUEUE) && (Packet->QueueType != NVME_IO_QUEUE)) { - return EFI_INVALID_PARAMETER; - } - - // - // 'Attributes' with neither EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL nor - // EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL set is an illegal - // configuration. - // - Attributes = This->Mode->Attributes; - if ((Attributes & (EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_PHYSICAL | - EFI_NVM_EXPRESS_PASS_THRU_ATTRIBUTES_LOGICAL)) == 0) - { - return EFI_INVALID_PARAMETER; - } - - // - // Buffer alignment check for TransferBuffer & MetadataBuffer. - // - IoAlign = This->Mode->IoAlign; - if ((IoAlign > 0) && (((UINTN)Packet->TransferBuffer & (IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } - - if ((IoAlign > 0) && (((UINTN)Packet->MetadataBuffer & (IoAlign - 1)) != 0)) { - return EFI_INVALID_PARAMETER; - } - - Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This); - - // - // Check NamespaceId is valid or not. - // - if ((NamespaceId > Private->ControllerData->Nn) && - (NamespaceId != (UINT32)-1)) - { - return EFI_INVALID_PARAMETER; - } - - // - // Check whether TransferLength exceeds the maximum data transfer size. - // - if (Private->ControllerData->Mdts != 0) { - MaxTransLen = (1 << (Private->ControllerData->Mdts)) * - (1 << (Private->Cap.Mpsmin + 12)); - if (Packet->TransferLength > MaxTransLen) { - Packet->TransferLength = MaxTransLen; - return EFI_BAD_BUFFER_SIZE; - } - } - - PciIo = Private->PciIo; - MapData = NULL; - MapMeta = NULL; - MapPrpList = NULL; - PrpListHost = NULL; - PrpListNo = 0; - Prp = NULL; - TimerEvent = NULL; - Status = EFI_SUCCESS; - // MS_HYP_CHANGE BEGIN - TransferBouncePageList = NULL; - MetadataBouncePageList = NULL; - // MS_HYP_CHANGE END - - // MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - if (PcdGetBool (PcdSupportAlternativeQueueSize)) { - QueueSize = MIN (NVME_ALTERNATIVE_MAX_QUEUE_SIZE, Private->Cap.Mqes) + 1; - } else { - QueueSize = MIN (NVME_ASYNC_CSQ_SIZE, Private->Cap.Mqes) + 1; - } - - // MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - - if (Packet->QueueType == NVME_ADMIN_QUEUE) { - QueueId = 0; - } else { - if (Event == NULL) { - QueueId = 1; - } else { - QueueId = 2; - - // - // Submission queue full check. - // - if ((Private->SqTdbl[QueueId].Sqt + 1) % QueueSize == - Private->AsyncSqHead) - { - return EFI_NOT_READY; - } - } - } - - Sq = Private->SqBuffer[QueueId] + Private->SqTdbl[QueueId].Sqt; - Cq = Private->CqBuffer[QueueId] + Private->CqHdbl[QueueId].Cqh; - - if (Packet->NvmeCmd->Nsid != NamespaceId) { - return EFI_INVALID_PARAMETER; - } - - // MU_CHANGE - Support alternative hardware queue sizes in NVME driver - // - // Nvme DXE driver polls phase bit for CQe completion. - // Explicitly assign phase bit with the bit before completion. - // A flipped phase bit will be assigned by device upon CQe completes. - // - Cq->Pt = Private->Pt[QueueId]; - - ZeroMem (Sq, sizeof (NVME_SQ)); - Sq->Opc = (UINT8)Packet->NvmeCmd->Cdw0.Opcode; - Sq->Fuse = (UINT8)Packet->NvmeCmd->Cdw0.FusedOperation; - Sq->Cid = Private->Cid[QueueId]++; - Sq->Nsid = Packet->NvmeCmd->Nsid; - - // - // Currently we only support PRP for data transfer, SGL is NOT supported. - // - ASSERT (Sq->Psdt == 0); - if (Sq->Psdt != 0) { - DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: doesn't support SGL mechanism\n")); - return EFI_UNSUPPORTED; - } - - Sq->Prp[0] = (UINT64)(UINTN)Packet->TransferBuffer; - if ((Packet->QueueType == NVME_ADMIN_QUEUE) && - ((Sq->Opc == NVME_ADMIN_CRIOCQ_CMD) || (Sq->Opc == NVME_ADMIN_CRIOSQ_CMD))) - { - // - // Currently, we only use the IO Completion/Submission queues created internally - // by this driver during controller initialization. Any other IO queues created - // will not be consumed here. The value is little to accept external IO queue - // creation requests, so here we will return EFI_UNSUPPORTED for external IO - // queue creation request. - // - if (!Private->CreateIoQueue) { - DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: Does not support external IO queues creation request.\n")); - return EFI_UNSUPPORTED; - } - } else if ((Sq->Opc & (BIT0 | BIT1)) != 0) { - // - // If the NVMe cmd has data in or out, then mapping the user buffer to the PCI controller specific addresses. - // - if (((Packet->TransferLength != 0) && (Packet->TransferBuffer == NULL)) || - ((Packet->TransferLength == 0) && (Packet->TransferBuffer != NULL))) - { - return EFI_INVALID_PARAMETER; - } - - if ((Sq->Opc & BIT0) != 0) { - Flag = EfiPciIoOperationBusMasterRead; - } else { - Flag = EfiPciIoOperationBusMasterWrite; - } - - if ((Packet->TransferLength != 0) && (Packet->TransferBuffer != NULL)) { - - // MS_HYP_CHANGE BEGIN - if (NvmExpressIsBounceActive()) { - - // - // Use bounce buffer for isolated VMs. - // - Offset = (UINT16)((UINT64)Packet->TransferBuffer & (EFI_PAGE_SIZE - 1)); - BouncePageCount = EFI_SIZE_TO_PAGES(Packet->TransferLength + Offset); - TransferBouncePageList = NvmExpressAcquireBouncePages (Private, - BouncePageCount); - if (TransferBouncePageList == NULL) { - DEBUG ((DEBUG_ERROR, "%a: Transfer bounce buffer allocation error - %r!\n", __func__, Status)); - Status = EFI_OUT_OF_RESOURCES; - goto EXIT; - } - - if ((Sq->Opc & BIT0) != 0) { - - // - // Data transfer direction from host to controller. Copy into bounce buffer. - // - NvmExpressCopyBouncePagesToExternalBuffer (Packet->TransferBuffer, - Packet->TransferLength, - TransferBouncePageList, - TRUE); - } else { - NvmExpressZeroBouncePageList (TransferBouncePageList); - } - PhyAddr = TransferBouncePageList->HostVisiblePA + Offset; - } else { - // MS_HYP_CHANGE END - MapLength = Packet->TransferLength; - Status = PciIo->Map ( - PciIo, - Flag, - Packet->TransferBuffer, - &MapLength, - &PhyAddr, - &MapData - ); - if (EFI_ERROR (Status) || (Packet->TransferLength != MapLength)) { - DEBUG ((DEBUG_ERROR, "%a: Map transfer buffer error - %r!\n", __func__, Status)); - Status = EFI_OUT_OF_RESOURCES; - goto EXIT; - } - - } // MS_HYP_CHANGE - - Sq->Prp[0] = PhyAddr; - - // MS_HYP_CHANGE this block is lifted from lower in the function to set Sq->Prp[1] correctly - // - // If the buffer size spans more than two memory pages (page size as defined in CC.Mps), - // then build a PRP list in the second PRP submission queue entry. - // - Offset = ((UINT16)Sq->Prp[0]) & (EFI_PAGE_SIZE - 1); - Bytes = Packet->TransferLength; - - if ((Offset + Bytes) > (EFI_PAGE_SIZE * 2)) { - // - // Create PrpList for remaining data buffer. - // - PhyAddr = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); - Prp = NvmeCreatePrpList (PciIo, - PhyAddr, - EFI_SIZE_TO_PAGES (Offset + Bytes) - 1, - // MS_HYP_CHANGE - ((TransferBouncePageList != NULL)? - TransferBouncePageList->NextBouncePage:NULL), - &PrpListHost, - &PrpListNo, - &MapPrpList, - &PrpListVisibilityContext); - if (Prp == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto EXIT; - } - - Sq->Prp[1] = (UINT64)(UINTN)Prp; - } else if ((Offset + Bytes) > EFI_PAGE_SIZE) { - - // MS_HYP_CHANGE BEGIN - if (TransferBouncePageList != NULL) { - // - // Next page in bounce buffer list - // - PNVME_BOUNCE_PAGE bouncePage; - bouncePage = TransferBouncePageList->NextBouncePage; - ASSERT (bouncePage != NULL); - - Sq->Prp[1] = bouncePage->HostVisiblePA; - } else { - // MS_HYP_CHANGE END - Sq->Prp[1] = (Sq->Prp[0] + EFI_PAGE_SIZE) & ~(EFI_PAGE_SIZE - 1); - } // MS_HYP_CHANGE - } - } - - if ((Packet->MetadataLength != 0) && (Packet->MetadataBuffer != NULL)) { - // MS_HYP_CHANGE BEGIN - if (NvmExpressIsBounceActive()) { - - // - // Use bounce buffer for isolated VMs. - // - Offset = (UINT16)((UINT64)Packet->MetadataBuffer & (EFI_PAGE_SIZE - 1)); - BouncePageCount = EFI_SIZE_TO_PAGES(Packet->MetadataLength + Offset); - - // - // Metadata buffer cannot span more than 1 page - // - ASSERT (BouncePageCount == 1); - MetadataBouncePageList = NvmExpressAcquireBouncePages (Private, - BouncePageCount); - if (MetadataBouncePageList == NULL) { - DEBUG ((DEBUG_ERROR, "%a: Metadata bounce buffer allocation error - %r!\n", __func__, Status)); - Status = EFI_OUT_OF_RESOURCES; - goto EXIT; - } - if ((Sq->Opc & BIT0) != 0) { - - // - // Data transfer direction from host to controller. Copy - // into bounce buffer. - // - NvmExpressCopyBouncePagesToExternalBuffer (Packet->MetadataBuffer, - Packet->MetadataLength, - MetadataBouncePageList, - TRUE); - } else { - NvmExpressZeroBouncePageList (MetadataBouncePageList); - } - PhyAddr = MetadataBouncePageList->HostVisiblePA + Offset; - } else { - // MS_HYP_CHANGE END - MapLength = Packet->MetadataLength; - Status = PciIo->Map ( - PciIo, - Flag, - Packet->MetadataBuffer, - &MapLength, - &PhyAddr, - &MapMeta - ); - if (EFI_ERROR (Status) || (Packet->MetadataLength != MapLength)) { - DEBUG ((DEBUG_ERROR, "%a: Map packet metadata buffer error - %r!\n", __func__, Status)); - Status = EFI_OUT_OF_RESOURCES; - goto EXIT; - } - } // MS_HYP_CHANGE - Sq->Mptr = PhyAddr; - } - } - - if (Packet->NvmeCmd->Flags & CDW2_VALID) { - Sq->Rsvd2 = (UINT64)Packet->NvmeCmd->Cdw2; - } - - if (Packet->NvmeCmd->Flags & CDW3_VALID) { - Sq->Rsvd2 |= LShiftU64 ((UINT64)Packet->NvmeCmd->Cdw3, 32); - } - - if (Packet->NvmeCmd->Flags & CDW10_VALID) { - Sq->Payload.Raw.Cdw10 = Packet->NvmeCmd->Cdw10; - } - - if (Packet->NvmeCmd->Flags & CDW11_VALID) { - Sq->Payload.Raw.Cdw11 = Packet->NvmeCmd->Cdw11; - } - - if (Packet->NvmeCmd->Flags & CDW12_VALID) { - Sq->Payload.Raw.Cdw12 = Packet->NvmeCmd->Cdw12; - } - - if (Packet->NvmeCmd->Flags & CDW13_VALID) { - Sq->Payload.Raw.Cdw13 = Packet->NvmeCmd->Cdw13; - } - - if (Packet->NvmeCmd->Flags & CDW14_VALID) { - Sq->Payload.Raw.Cdw14 = Packet->NvmeCmd->Cdw14; - } - - if (Packet->NvmeCmd->Flags & CDW15_VALID) { - Sq->Payload.Raw.Cdw15 = Packet->NvmeCmd->Cdw15; - } - - // MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - if (PcdGetBool (PcdSupportAlternativeQueueSize)) { - Private->SqTdbl[QueueId].Sqt = (Private->SqTdbl[QueueId].Sqt + 1) % QueueSize; - } else { - // - // Ring the submission queue doorbell. - // - if ((Event != NULL) && (QueueId != 0)) { - Private->SqTdbl[QueueId].Sqt = - (Private->SqTdbl[QueueId].Sqt + 1) % QueueSize; - } else { - Private->SqTdbl[QueueId].Sqt ^= 1; - } - } - - // MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - - Data = ReadUnaligned32 ((UINT32 *)&Private->SqTdbl[QueueId]); - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_SQTDBL_OFFSET (QueueId, Private->Cap.Dstrd), - 1, - &Data - ); - - if (EFI_ERROR (Status)) { - goto EXIT; - } - - // - // For non-blocking requests, return directly if the command is placed - // in the submission queue. - // - if ((Event != NULL) && (QueueId != 0)) { - AsyncRequest = AllocateZeroPool (sizeof (NVME_PASS_THRU_ASYNC_REQ)); - if (AsyncRequest == NULL) { - Status = EFI_DEVICE_ERROR; - goto EXIT; - } - - AsyncRequest->Signature = NVME_PASS_THRU_ASYNC_REQ_SIG; - AsyncRequest->Packet = Packet; - AsyncRequest->CommandId = Sq->Cid; - AsyncRequest->CallerEvent = Event; - AsyncRequest->MapData = MapData; - AsyncRequest->MapMeta = MapMeta; - AsyncRequest->MapPrpList = MapPrpList; - AsyncRequest->PrpListNo = PrpListNo; - AsyncRequest->PrpListHost = PrpListHost; - // MS_HYP_CHANGE BEGIN - AsyncRequest->PrpListHostVisibilityContext.RangeProtectionHandle = PrpListVisibilityContext.RangeProtectionHandle; - AsyncRequest->TransferBouncePageList = TransferBouncePageList; - AsyncRequest->MetadataBouncePageList = MetadataBouncePageList; - // MS_HYP_CHANGE END - - OldTpl = gBS->RaiseTPL (TPL_NOTIFY); - InsertTailList (&Private->AsyncPassThruQueue, &AsyncRequest->Link); - gBS->RestoreTPL (OldTpl); - - return EFI_SUCCESS; - } - - Status = gBS->CreateEvent ( - EVT_TIMER, - TPL_CALLBACK, - NULL, - NULL, - &TimerEvent - ); - if (EFI_ERROR (Status)) { - goto EXIT; - } - - Status = gBS->SetTimer (TimerEvent, TimerRelative, Packet->CommandTimeout); - - if (EFI_ERROR (Status)) { - goto EXIT; - } - - // - // Wait for completion queue to get filled in. - // - Status = EFI_TIMEOUT; - while (EFI_ERROR (gBS->CheckEvent (TimerEvent))) { - if (Cq->Pt != Private->Pt[QueueId]) { - Status = EFI_SUCCESS; - break; - } - } - - // - // Check the NVMe cmd execution result - // - if (Status != EFI_TIMEOUT) { - if ((Cq->Sct == 0) && (Cq->Sc == 0)) { - Status = EFI_SUCCESS; - - // MS_HYP_CHANGE BEGIN - // - // Copy back data from the bounce buffers - // - if (Packet->NvmeCmd->Cdw0.Opcode & BIT1) { - if (TransferBouncePageList != NULL) { - NvmExpressCopyBouncePagesToExternalBuffer(Packet->TransferBuffer, - Packet->TransferLength, - TransferBouncePageList, - FALSE); - } - - if (MetadataBouncePageList != NULL) { - NvmExpressCopyBouncePagesToExternalBuffer(Packet->MetadataBuffer, - Packet->MetadataLength, - MetadataBouncePageList, - FALSE); - } - } - // MS_HYP_CHANGE END - } else { - Status = EFI_DEVICE_ERROR; - // - // Dump every completion entry status for debugging. - // - DEBUG_CODE_BEGIN (); - NvmeDumpStatus ((NVME_CQ *)Cq); - DEBUG_CODE_END (); - } - - // - // Copy the Respose Queue entry for this command to the callers response buffer - // - 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. - // - DEBUG ((DEBUG_ERROR, "NvmExpressPassThru: Timeout occurs for an NVMe command.\n")); - - // - // Disable the timer to trigger the process of async transfers temporarily. - // - Status = gBS->SetTimer (Private->TimerEvent, TimerCancel, 0); - if (EFI_ERROR (Status)) { - goto EXIT; - } - - // - // Reset the NVMe controller. - // - Status = NvmeControllerReset (Private); // MU_CHANGE - Allocate IO Queue Buffer - if (!EFI_ERROR (Status)) { - Status = AbortAsyncPassThruTasks (Private); - if (!EFI_ERROR (Status)) { - // - // Re-enable the timer to trigger the process of async transfers. - // - Status = gBS->SetTimer (Private->TimerEvent, TimerPeriodic, NVME_HC_ASYNC_TIMER); - if (!EFI_ERROR (Status)) { - // - // Return EFI_TIMEOUT to indicate a timeout occurs for NVMe PassThru command. - // - Status = EFI_TIMEOUT; - } - } - } else { - Status = EFI_DEVICE_ERROR; - } - - goto EXIT; - } - - // MU_CHANGE [BEGIN] - Support alternative hardware queue sizes in NVME driver - if (PcdGetBool (PcdSupportAlternativeQueueSize)) { - Private->CqHdbl[QueueId].Cqh = (Private->CqHdbl[QueueId].Cqh + 1) % QueueSize; - if (Private->CqHdbl[QueueId].Cqh == 0) { - Private->Pt[QueueId] ^= 1; - } - } else { - if ((Private->CqHdbl[QueueId].Cqh ^= 1) == 0) { - Private->Pt[QueueId] ^= 1; - } - } - - // MU_CHANGE [END] - Support alternative hardware queue sizes in NVME driver - - Data = ReadUnaligned32 ((UINT32 *)&Private->CqHdbl[QueueId]); - PreviousStatus = Status; - Status = PciIo->Mem.Write ( - PciIo, - EfiPciIoWidthUint32, - NVME_BAR, - NVME_CQHDBL_OFFSET (QueueId, Private->Cap.Dstrd), - 1, - &Data - ); - // The return status of PciIo->Mem.Write should not override - // previous status if previous status contains error. - Status = EFI_ERROR (PreviousStatus) ? PreviousStatus : Status; - - // - // For now, the code does not support the non-blocking feature for admin queue. - // If Event is not NULL for admin queue, signal the caller's event here. - // - if (Event != NULL) { - ASSERT (QueueId == 0); - gBS->SignalEvent (Event); - } - -EXIT: - // MS_HYP_CHANGE BEGIN - if (TransferBouncePageList != NULL) { - NvmExpressReleaseBouncePages (Private, TransferBouncePageList); - } - - if (MetadataBouncePageList != NULL) { - NvmExpressReleaseBouncePages (Private, MetadataBouncePageList); - } - // MS_HYP_CHANGE END - - if (MapData != NULL) { - PciIo->Unmap ( - PciIo, - MapData - ); - } - - if (MapMeta != NULL) { - PciIo->Unmap ( - PciIo, - MapMeta - ); - } - - if (MapPrpList != NULL) { - PciIo->Unmap ( - PciIo, - MapPrpList - ); - } - - if (PrpListHost != NULL) { - // MS_HYP_CHANGE BEGIN - if (IsIsolated()) { - NvmExpressMakeAddressRangePrivate(&PrpListVisibilityContext, PrpListHost); - } - // MS_HYP_CHANGE END - PciIo->FreeBuffer (PciIo, PrpListNo, PrpListHost); - PrpListHost = NULL; - } - - if (TimerEvent != NULL) { - gBS->CloseEvent (TimerEvent); - } - - return Status; -} - -/** - Used to retrieve the next namespace ID for this NVM Express controller. - - The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNextNamespace() function retrieves the next valid - namespace ID on this NVM Express controller. - - If on input the value pointed to by NamespaceId is 0xFFFFFFFF, then the first valid namespace - ID defined on the NVM Express controller is returned in the location pointed to by NamespaceId - and a status of EFI_SUCCESS is returned. - - If on input the value pointed to by NamespaceId is an invalid namespace ID other than 0xFFFFFFFF, - then EFI_INVALID_PARAMETER is returned. - - If on input the value pointed to by NamespaceId is a valid namespace ID, then the next valid - namespace ID on the NVM Express controller is returned in the location pointed to by NamespaceId, - and EFI_SUCCESS is returned. - - If the value pointed to by NamespaceId is the namespace ID of the last namespace on the NVM - Express controller, then EFI_NOT_FOUND is returned. - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @param[in,out] NamespaceId On input, a pointer to a legal NamespaceId for an NVM Express - namespace present on the NVM Express controller. On output, a - pointer to the next NamespaceId of an NVM Express namespace on - an NVM Express controller. An input value of 0xFFFFFFFF retrieves - the first NamespaceId for an NVM Express namespace present on an - NVM Express controller. - - @retval EFI_SUCCESS The Namespace ID of the next Namespace was returned. - @retval EFI_NOT_FOUND There are no more namespaces defined on this controller. - @retval EFI_INVALID_PARAMETER NamespaceId is an invalid value other than 0xFFFFFFFF. - -**/ -EFI_STATUS -EFIAPI -NvmExpressGetNextNamespace ( - IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, - IN OUT UINT32 *NamespaceId - ) -{ - NVME_CONTROLLER_PRIVATE_DATA *Private; - NVME_ADMIN_NAMESPACE_DATA *NamespaceData; - UINT32 NextNamespaceId; - EFI_STATUS Status; - - if ((This == NULL) || (NamespaceId == NULL)) { - return EFI_INVALID_PARAMETER; - } - - NamespaceData = NULL; - Status = EFI_NOT_FOUND; - - Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This); - // - // If the NamespaceId input value is 0xFFFFFFFF, then get the first valid namespace ID - // - if (*NamespaceId == 0xFFFFFFFF) { - // - // Start with the first namespace ID - // - NextNamespaceId = 1; - // - // Allocate buffer for Identify Namespace data. - // - NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA)); - - if (NamespaceData == NULL) { - return EFI_NOT_FOUND; - } - - Status = NvmeIdentifyNamespace (Private, NextNamespaceId, NamespaceData); - if (EFI_ERROR (Status)) { - goto Done; - } - - *NamespaceId = NextNamespaceId; - } else { - if (*NamespaceId > Private->ControllerData->Nn) { - return EFI_INVALID_PARAMETER; - } - - NextNamespaceId = *NamespaceId + 1; - if (NextNamespaceId > Private->ControllerData->Nn) { - return EFI_NOT_FOUND; - } - - // - // Allocate buffer for Identify Namespace data. - // - NamespaceData = (NVME_ADMIN_NAMESPACE_DATA *)AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA)); - if (NamespaceData == NULL) { - return EFI_NOT_FOUND; - } - - Status = NvmeIdentifyNamespace (Private, NextNamespaceId, NamespaceData); - if (EFI_ERROR (Status)) { - goto Done; - } - - *NamespaceId = NextNamespaceId; - } - -Done: - if (NamespaceData != NULL) { - FreePool (NamespaceData); - } - - return Status; -} - -/** - Used to translate a device path node to a namespace ID. - - The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.GetNamespace() function determines the namespace ID associated with the - namespace described by DevicePath. - - If DevicePath is a device path node type that the NVM Express Pass Thru driver supports, then the NVM Express - Pass Thru driver will attempt to translate the contents DevicePath into a namespace ID. - - If this translation is successful, then that namespace ID is returned in NamespaceId, and EFI_SUCCESS is returned - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @param[in] DevicePath A pointer to the device path node that describes an NVM Express namespace on - the NVM Express controller. - @param[out] NamespaceId The NVM Express namespace ID contained in the device path node. - - @retval EFI_SUCCESS DevicePath was successfully translated to NamespaceId. - @retval EFI_INVALID_PARAMETER If DevicePath or NamespaceId are NULL, then EFI_INVALID_PARAMETER is returned. - @retval EFI_UNSUPPORTED If DevicePath is not a device path node type that the NVM Express Pass Thru driver - supports, then EFI_UNSUPPORTED is returned. - @retval EFI_NOT_FOUND If DevicePath is a device path node type that the NVM Express Pass Thru driver - supports, but there is not a valid translation from DevicePath to a namespace ID, - then EFI_NOT_FOUND is returned. -**/ -EFI_STATUS -EFIAPI -NvmExpressGetNamespace ( - IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, - OUT UINT32 *NamespaceId - ) -{ - NVME_NAMESPACE_DEVICE_PATH *Node; - NVME_CONTROLLER_PRIVATE_DATA *Private; - - if ((This == NULL) || (DevicePath == NULL) || (NamespaceId == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (DevicePath->Type != MESSAGING_DEVICE_PATH) { - return EFI_UNSUPPORTED; - } - - Node = (NVME_NAMESPACE_DEVICE_PATH *)DevicePath; - Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This); - - if (DevicePath->SubType == MSG_NVME_NAMESPACE_DP) { - if (DevicePathNodeLength (DevicePath) != sizeof (NVME_NAMESPACE_DEVICE_PATH)) { - return EFI_NOT_FOUND; - } - - // - // Check NamespaceId in the device path node is valid or not. - // - if ((Node->NamespaceId == 0) || - (Node->NamespaceId > Private->ControllerData->Nn)) - { - return EFI_NOT_FOUND; - } - - *NamespaceId = Node->NamespaceId; - - return EFI_SUCCESS; - } else { - return EFI_UNSUPPORTED; - } -} - -/** - Used to allocate and build a device path node for an NVM Express namespace on an NVM Express controller. - - The EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL.BuildDevicePath() function allocates and builds a single device - path node for the NVM Express namespace specified by NamespaceId. - - If the NamespaceId is not valid, then EFI_NOT_FOUND is returned. - - If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned. - - If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES is returned. - - Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of DevicePath are - initialized to describe the NVM Express namespace specified by NamespaceId, and EFI_SUCCESS is returned. - - @param[in] This A pointer to the EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL instance. - @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,out] DevicePath A pointer to a single device path node that describes the NVM Express - namespace specified by NamespaceId. This function is responsible for - allocating the buffer DevicePath with the boot service AllocatePool(). - It is the caller's responsibility to free DevicePath when the caller - is finished with DevicePath. - @retval EFI_SUCCESS The device path node that describes the NVM Express namespace specified - by NamespaceId was allocated and returned in DevicePath. - @retval EFI_NOT_FOUND The NamespaceId is not valid. - @retval EFI_INVALID_PARAMETER DevicePath is NULL. - @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the DevicePath node. - -**/ -EFI_STATUS -EFIAPI -NvmExpressBuildDevicePath ( - IN EFI_NVM_EXPRESS_PASS_THRU_PROTOCOL *This, - IN UINT32 NamespaceId, - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ) -{ - NVME_NAMESPACE_DEVICE_PATH *Node; - NVME_CONTROLLER_PRIVATE_DATA *Private; - EFI_STATUS Status; - NVME_ADMIN_NAMESPACE_DATA *NamespaceData; - - // - // Validate parameters - // - if ((This == NULL) || (DevicePath == NULL)) { - return EFI_INVALID_PARAMETER; - } - - Status = EFI_SUCCESS; - Private = NVME_CONTROLLER_PRIVATE_DATA_FROM_PASS_THRU (This); - - // - // Check NamespaceId is valid or not. - // - if ((NamespaceId == 0) || - (NamespaceId > Private->ControllerData->Nn)) - { - return EFI_NOT_FOUND; - } - - Node = (NVME_NAMESPACE_DEVICE_PATH *)AllocateZeroPool (sizeof (NVME_NAMESPACE_DEVICE_PATH)); - if (Node == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Node->Header.Type = MESSAGING_DEVICE_PATH; - Node->Header.SubType = MSG_NVME_NAMESPACE_DP; - SetDevicePathNodeLength (&Node->Header, sizeof (NVME_NAMESPACE_DEVICE_PATH)); - Node->NamespaceId = NamespaceId; - - // - // Allocate a buffer for Identify Namespace data. - // - NamespaceData = NULL; - NamespaceData = AllocateZeroPool (sizeof (NVME_ADMIN_NAMESPACE_DATA)); - if (NamespaceData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Exit; - } - - // - // Get UUID from specified Identify Namespace data. - // - Status = NvmeIdentifyNamespace ( - Private, - NamespaceId, - (VOID *)NamespaceData - ); - - if (EFI_ERROR (Status)) { - goto Exit; - } - - Node->NamespaceUuid = NamespaceData->Eui64; - - *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Node; - -Exit: - if (NamespaceData != NULL) { - FreePool (NamespaceData); - } - - if (EFI_ERROR (Status)) { - FreePool (Node); - } - - return Status; -} diff --git a/MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c b/MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c deleted file mode 100644 index 9227ef8ab..000000000 --- a/MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTest.c +++ /dev/null @@ -1,983 +0,0 @@ -/** @file -- MediaSanitizeUnitTest.c - Placeholder/framework for developing a Media Sanitize unit test package. - - Copyright (c) Microsoft Corporation. - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../NvmExpress.h" -#include "../NvmExpressBlockIo.h" -#include "../NvmExpressMediaSanitize.h" -#include "../NvmExpressHci.h" - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -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; -} - -UNIT_TEST_STATUS -EFIAPI -MediaSanitizePurgeUnitTest ( - IN UNIT_TEST_CONTEXT Context - ) -{ - UINT32 PurgeAction; - UINT32 OverwritePattern; - UNIT_TEST_STATUS UnitTestStatus = UNIT_TEST_PASSED; - NVME_DEVICE_PRIVATE_DATA *NvmeDevice = NULL; - EFI_STATUS 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; -} - -UNIT_TEST_STATUS -EFIAPI -NvmeSanitizeUnitTest ( - IN UNIT_TEST_CONTEXT Context - ) -{ - UINT32 NamespaceId = 0; - UINT32 SanitizeAction; - UINT32 NoDeallocateAfterSanitize; - UINT32 OverwritePattern; - UNIT_TEST_STATUS UnitTestStatus = UNIT_TEST_PASSED; - NVME_DEVICE_PRIVATE_DATA *NvmeDevice = NULL; - EFI_STATUS 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; -} - -UNIT_TEST_STATUS -EFIAPI -NvmeFormatNvmUnitTest ( - IN UNIT_TEST_CONTEXT Context - ) -{ - UINT32 NamespaceId = 0; - UINT32 Ses; - UINT32 Flbas; - NVME_DEVICE_PRIVATE_DATA *NvmeDevice = NULL; - UNIT_TEST_STATUS UnitTestStatus = UNIT_TEST_PASSED; - EFI_STATUS 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; -} - -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; -} - -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; -} - -int -main ( - int argc, - char *argv[] - ) -{ - return MediaSanitizeUnitTestEntry (); -} diff --git a/MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf b/MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf deleted file mode 100644 index 0997ef0e3..000000000 --- a/MsvmPkg/NvmExpressDxe/UnitTest/MediaSanitizeUnitTestHost.inf +++ /dev/null @@ -1,37 +0,0 @@ -## @file -# Unit tests for MEDIA_SANITIZE_PROTOCOL and mapping to NVM Express native commands (Sanitize and FormatNVM) -# -# Copyright (C) Microsoft Corporation. -# 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/MsvmPkg/VpcivscDxe/VpcivscDxe.inf b/MsvmPkg/VpcivscDxe/VpcivscDxe.inf index f0c085cbb..898ebee89 100644 --- a/MsvmPkg/VpcivscDxe/VpcivscDxe.inf +++ b/MsvmPkg/VpcivscDxe/VpcivscDxe.inf @@ -19,6 +19,7 @@ [Packages] MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec MsvmPkg/MsvmPkg.dec [LibraryClasses] @@ -29,6 +30,7 @@ DevicePathLib EmclLib IoLib + IoMmuLib IsolationLib MemoryAllocationLib MmioAllocationLib diff --git a/MsvmPkg/VpcivscDxe/VpcivscPciIo.c b/MsvmPkg/VpcivscDxe/VpcivscPciIo.c index 565655d36..262f3fcab 100644 --- a/MsvmPkg/VpcivscDxe/VpcivscPciIo.c +++ b/MsvmPkg/VpcivscDxe/VpcivscPciIo.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -581,10 +582,44 @@ VpcivscPciIoMap( OUT VOID **Mapping ) { - // For VPCI, the VSC has DMA access to all pages. So nothing to do here, - // just return the address of the buffer. + if (IoMmuIsPresent ()) { + // + // Isolated VM: delegate to the IOMMU protocol for bounce buffering. + // EFI_PCI_IO_PROTOCOL_OPERATION maps directly to EDKII_IOMMU_OPERATION + // because the BusMasterRead / BusMasterWrite / BusMasterCommonBuffer + // members share the same ordinal values (0, 1, 2) in both enums. + // The STATIC_ASSERTs below catch any future divergence at compile time. + // + STATIC_ASSERT ( + (UINT32)EfiPciIoOperationBusMasterRead == + (UINT32)EdkiiIoMmuOperationBusMasterRead, + "EFI_PCI_IO_PROTOCOL_OPERATION/EDKII_IOMMU_OPERATION BusMasterRead mismatch" + ); + STATIC_ASSERT ( + (UINT32)EfiPciIoOperationBusMasterWrite == + (UINT32)EdkiiIoMmuOperationBusMasterWrite, + "EFI_PCI_IO_PROTOCOL_OPERATION/EDKII_IOMMU_OPERATION BusMasterWrite mismatch" + ); + STATIC_ASSERT ( + (UINT32)EfiPciIoOperationBusMasterCommonBuffer == + (UINT32)EdkiiIoMmuOperationBusMasterCommonBuffer, + "EFI_PCI_IO_PROTOCOL_OPERATION/EDKII_IOMMU_OPERATION BusMasterCommonBuffer mismatch" + ); + + return IoMmuMap ( + (EDKII_IOMMU_OPERATION)Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + } - *DeviceAddress = (UINTN) HostAddress; + // + // No IoMmu bounce case: the VSC has DMA access to all pages. + // Just return the address of the buffer. + // + *DeviceAddress = (UINTN)HostAddress; *Mapping = NULL; return EFI_SUCCESS; @@ -606,10 +641,11 @@ VpcivscPciIoUnmap( IN VOID *Mapping ) { - // DEBUG((DEBUG_VPCI_INFO, "VpcivscPciIoUnmap called with mapping %llx\n", Mapping)); - - ASSERT(Mapping == NULL); + if (IoMmuIsPresent ()) { + return IoMmuUnmap (Mapping); + } + // No IoMmu bounce case: nothing to do since Map is a noop. return EFI_SUCCESS; } @@ -644,36 +680,37 @@ VpcivscPciIoAllocateBuffer( IN UINT64 Attributes ) { - VOID* buffer = NULL; - - DEBUG((DEBUG_VPCI_INFO, "VpcivscPciIoAllocateBuffer called with pages %x\n", Pages)); - - // For VPCI, the VSC has DMA access to all pages. So nothing special here, - // just allocate memory like normal. + DEBUG ((DEBUG_VPCI_INFO, "VpcivscPciIoAllocateBuffer called with pages %x\n", Pages)); + + if (IoMmuIsPresent ()) { + // + // Isolated VM: delegate to the IOMMU protocol which allocates + // host-visible memory and returns a shared VA. + // + return IoMmuAllocateBuffer (Type, MemoryType, Pages, HostAddress, Attributes); + } - // NVMe dxe driver doesn't use attributes. + // + // Non-isolated VM: just allocate memory normally. + // if (Attributes != 0) { - ASSERT(FALSE); + ASSERT (FALSE); return EFI_UNSUPPORTED; } if (MemoryType != EfiBootServicesData) { - ASSERT(FALSE); + ASSERT (FALSE); return EFI_UNSUPPORTED; } - buffer = AllocatePages(Pages); - - if (buffer == NULL) + *HostAddress = AllocatePages (Pages); + if (*HostAddress == NULL) { return EFI_OUT_OF_RESOURCES; } - // The host address is just the buffer address. No special mapping. - *HostAddress = buffer; - return EFI_SUCCESS; } @@ -685,14 +722,17 @@ VpcivscPciIoFreeBuffer( IN VOID *HostAddress ) { - DEBUG((DEBUG_VPCI_INFO, "VpcivscPciIoFreeBuffer called with addr %llx pages %x\n", HostAddress, Pages)); - - // Free the buffer allocated with AllocatePages - // FreePages(HostAddress, Pages); - // NOTE: To workaround a bug with ND2 on the host registering write - // notifications for pages resulting in the VM hanging, do not put - // pages used for NVMe queues back onto the free list. Instead, - // leak these pages as they will be reclaimed later at ExitBootServices. + DEBUG ((DEBUG_VPCI_INFO, "VpcivscPciIoFreeBuffer called with addr %llx pages %x\n", HostAddress, Pages)); + + if (IoMmuIsPresent ()) { + // + // Isolated VM: delegate to the IOMMU protocol which revokes + // host visibility and frees the pages. + // + return IoMmuFreeBuffer (Pages, HostAddress); + } + + FreePages (HostAddress, Pages); return EFI_SUCCESS; }