From 4c4f50513382298279d347e6ea8ffe5b2aa55b11 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Mon, 9 Aug 2021 21:39:38 +0800 Subject: [PATCH 01/26] IntelSiliconPkg/PeiSmmAccessLib: Remove S3 requirement REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3539 PeiInstallSmmAccessPpi() currently requires the boot mode be set to S3 to actually install gEfiPeiMmAccessPpiGuid. This change removes this requirement in the function implementation for two reasons: 1. Practical use cases exist to require this PPI in cases other than the boot mode being set to BOOT_ON_S3_RESUME. 2. It is poor API design to implicitly bury this requirement within a function whose responsibility is to install the PPI. The caller can easily place arbitrary constraints around whether to call based on conditions such as the boot mode being BOOT_ON_S3_RESUME. Reviewed-by: Ray Ni Reviewed-by: Rangasai V Chaganty Signed-off-by: Michael Kubacki --- .../Library/PeiSmmAccessLib/PeiSmmAccessLib.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/IntelSiliconPkg/Feature/SmmAccess/Library/PeiSmmAccessLib/PeiSmmAccessLib.c b/IntelSiliconPkg/Feature/SmmAccess/Library/PeiSmmAccessLib/PeiSmmAccessLib.c index 391429c512..cccf65f920 100644 --- a/IntelSiliconPkg/Feature/SmmAccess/Library/PeiSmmAccessLib/PeiSmmAccessLib.c +++ b/IntelSiliconPkg/Feature/SmmAccess/Library/PeiSmmAccessLib/PeiSmmAccessLib.c @@ -252,19 +252,7 @@ PeiInstallSmmAccessPpi ( EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock; SMM_ACCESS_PRIVATE_DATA *SmmAccessPrivate; VOID *HobList; - EFI_BOOT_MODE BootMode; - Status = PeiServicesGetBootMode (&BootMode); - if (EFI_ERROR (Status)) { - // - // If not in S3 boot path. do nothing - // - return EFI_SUCCESS; - } - - if (BootMode != BOOT_ON_S3_RESUME) { - return EFI_SUCCESS; - } // // Initialize private data // From 25f8a6e067a4d10d3a72031f27687bfb41d8b666 Mon Sep 17 00:00:00 2001 From: Michael Holland Date: Tue, 28 Sep 2021 21:05:58 -0500 Subject: [PATCH 02/26] IntelSiliconPkg/FirmwareInterfaceTable: Define FIT 4 record Define FIT 4 record Signed-off-by: Michael Holland Reviewed-by: Sai Chaganty --- .../Include/IndustryStandard/FirmwareInterfaceTable.h | 1 + 1 file changed, 1 insertion(+) diff --git a/IntelSiliconPkg/Include/IndustryStandard/FirmwareInterfaceTable.h b/IntelSiliconPkg/Include/IndustryStandard/FirmwareInterfaceTable.h index 195b8287ee..470696fe21 100644 --- a/IntelSiliconPkg/Include/IndustryStandard/FirmwareInterfaceTable.h +++ b/IntelSiliconPkg/Include/IndustryStandard/FirmwareInterfaceTable.h @@ -17,6 +17,7 @@ #define FIT_TYPE_00_HEADER 0x00 #define FIT_TYPE_01_MICROCODE 0x01 #define FIT_TYPE_02_STARTUP_ACM 0x02 +#define FIT_TYPE_04_PROT_BOOT_POLICY 0x04 #define FIT_TYPE_07_BIOS_STARTUP_MODULE 0x07 #define FIT_TYPE_08_TPM_POLICY 0x08 #define FIT_TYPE_09_BIOS_POLICY 0x09 From c8844588f59b8cfc3f8337c82f0db4a8e8cad824 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 13:42:38 -0700 Subject: [PATCH 03/26] IntelSiliconPkg: Add BIOS area base address and size PCDs REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 Adds the following PCDs to IntelSiliconPkg.dec to consolidate the PCD to a single silicon declaration file. This allows libraries and modules in IntelSiliconPkg to be able to use this PCD. gIntelSiliconPkgTokenSpaceGuid.PcdBiosAreaBaseAddress gIntelSiliconPkgTokenSpaceGuid.PcdBiosSize Cc: Ray Ni Cc: Rangasai V Chaganty Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone Reviewed-by: Sai Chaganty --- IntelSiliconPkg/IntelSiliconPkg.dec | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index 92be71de5d..aac3ce28a7 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -88,6 +88,10 @@ # @Prompt Shadow all microcode update patches. gIntelSiliconPkgTokenSpaceGuid.PcdShadowAllMicrocode|FALSE|BOOLEAN|0x00000006 +[PcdsFixedAtBuild] + gIntelSiliconPkgTokenSpaceGuid.PcdBiosAreaBaseAddress|0xFF800000|UINT32|0x00000007 + gIntelSiliconPkgTokenSpaceGuid.PcdBiosSize|0x00800000|UINT32|0x00000008 + [PcdsFixedAtBuild, PcdsPatchableInModule] ## Error code for VTd error.

# EDKII_ERROR_CODE_VTD_ERROR = (EFI_IO_BUS_UNSPECIFIED | (EFI_OEM_SPECIFIC | 0x00000000)) = 0x02008000
From 57d62ce8a6bb329e753b043b20192f229af8305e Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 13:42:39 -0700 Subject: [PATCH 04/26] IntelSiliconPkg: Add microcode FV PCDs REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 Adds the following PCDs to IntelSiliconPkg.dec to consolidate the PCD to a single silicon declaration file. This allows libraries modules in IntelSiliconPkg to be able to use this PCD. gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvOffset Cc: Ray Ni Cc: Rangasai V Chaganty Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone --- IntelSiliconPkg/IntelSiliconPkg.dec | 3 +++ 1 file changed, 3 insertions(+) diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index aac3ce28a7..a8dbd0dce0 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -91,6 +91,9 @@ [PcdsFixedAtBuild] gIntelSiliconPkgTokenSpaceGuid.PcdBiosAreaBaseAddress|0xFF800000|UINT32|0x00000007 gIntelSiliconPkgTokenSpaceGuid.PcdBiosSize|0x00800000|UINT32|0x00000008 + gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase|0xFFE60000|UINT32|0x00000009 + gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize|0x000A0000|UINT32|0x0000000A + gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvOffset|0x00660000|UINT32|0x0000000B [PcdsFixedAtBuild, PcdsPatchableInModule] ## Error code for VTd error.

From 84a7aa855449667445eeadec56273df10b9554f1 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 13:42:40 -0700 Subject: [PATCH 05/26] IntelSiliconPkg: Add PCH SPI PPI REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 This SPI PPI definition is intended to serve as the single definition for Intel platform and silicon packages. Cc: Ray Ni Cc: Rangasai V Chaganty Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone Reviewed-by: Sai Chaganty --- IntelSiliconPkg/Include/Ppi/Spi.h | 25 +++++++++++++++++++++++++ IntelSiliconPkg/IntelSiliconPkg.dec | 3 +++ 2 files changed, 28 insertions(+) create mode 100644 IntelSiliconPkg/Include/Ppi/Spi.h diff --git a/IntelSiliconPkg/Include/Ppi/Spi.h b/IntelSiliconPkg/Include/Ppi/Spi.h new file mode 100644 index 0000000000..e1e6530f59 --- /dev/null +++ b/IntelSiliconPkg/Include/Ppi/Spi.h @@ -0,0 +1,25 @@ +/** @file + This file defines the PCH SPI PPI which implements the + Intel(R) PCH SPI Host Controller Compatibility Interface. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _PCH_SPI_PPI_H_ +#define _PCH_SPI_PPI_H_ + +#include + +// +// Extern the GUID for PPI users. +// +extern EFI_GUID gPchSpiPpiGuid; + +/** + Reuse the PCH_SPI_PROTOCOL definitions + This is possible becaues the PPI implementation does not rely on a PeiService pointer, + as it uses EDKII Glue Lib to do IO accesses +**/ +typedef PCH_SPI_PROTOCOL PCH_SPI_PPI; + +#endif diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index a8dbd0dce0..3b7c3a1a1e 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -71,6 +71,9 @@ gEdkiiMicrocodeStorageTypeFlashGuid = { 0x2cba01b3, 0xd391, 0x4598, { 0x8d, 0x89, 0xb7, 0xfc, 0x39, 0x22, 0xfd, 0x71 } } [Ppis] + ## Include/Ppi/Spi.h + gPchSpiPpiGuid = { 0x104c7177, 0xc2e6, 0x44f0, { 0xae, 0xe3, 0x9d, 0x0d, 0x9a, 0x52, 0xca, 0xdf } } + gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } } gEdkiiVTdNullRootEntryTableGuid = { 0x3de0593f, 0x6e3e, 0x4542, { 0xa1, 0xcb, 0xcb, 0xb2, 0xdb, 0xeb, 0xd8, 0xff } } From 7b05a91e27ca1be4b1c5471bcdaa972249c74fbd Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 13:42:41 -0700 Subject: [PATCH 06/26] IntelSiliconPkg: Add PCH SPI Protocol REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 These SPI Protocol definitions are intended to serve as the single definitions for Intel platform and silicon packages. 1. gPchSpiProtocolGuid 2. gPchSmmSpiProtocolGuid Cc: Ray Ni Cc: Rangasai V Chaganty Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone --- IntelSiliconPkg/Include/Protocol/Spi.h | 301 +++++++++++++++++++++++++ IntelSiliconPkg/IntelSiliconPkg.dec | 5 + 2 files changed, 306 insertions(+) create mode 100644 IntelSiliconPkg/Include/Protocol/Spi.h diff --git a/IntelSiliconPkg/Include/Protocol/Spi.h b/IntelSiliconPkg/Include/Protocol/Spi.h new file mode 100644 index 0000000000..f3e4607a29 --- /dev/null +++ b/IntelSiliconPkg/Include/Protocol/Spi.h @@ -0,0 +1,301 @@ +/** @file + This file defines the PCH SPI Protocol which implements the + Intel(R) PCH SPI Host Controller Compatibility Interface. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _PCH_SPI_PROTOCOL_H_ +#define _PCH_SPI_PROTOCOL_H_ + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gPchSpiProtocolGuid; +extern EFI_GUID gPchSmmSpiProtocolGuid; + +// +// Forward reference for ANSI C compatibility +// +typedef struct _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL; + +// +// SPI protocol data structures and definitions +// + +/** + Flash Region Type +**/ +typedef enum { + FlashRegionDescriptor, + FlashRegionBios, + FlashRegionMe, + FlashRegionGbE, + FlashRegionPlatformData, + FlashRegionDer, + FlashRegionSecondaryBios, + FlashRegionuCodePatch, + FlashRegionEC, + FlashRegionDeviceExpansion2, + FlashRegionIE, + FlashRegion10Gbe_A, + FlashRegion10Gbe_B, + FlashRegion13, + FlashRegion14, + FlashRegion15, + FlashRegionAll, + FlashRegionMax +} FLASH_REGION_TYPE; +// +// Protocol member functions +// + +/** + Read data from the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor. + @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. + @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ) ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + IN UINT32 Address, + IN UINT32 ByteCount, + OUT UINT8 *Buffer + ); + +/** + Write data to the flash part. Remark: Erase may be needed before write to the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor. + @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. + @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_WRITE) ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + IN UINT32 Address, + IN UINT32 ByteCount, + IN UINT8 *Buffer + ); + +/** + Erase some area on the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor. + @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_ERASE) ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + IN UINT32 Address, + IN UINT32 ByteCount + ); + +/** + Read SFDP data from the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] ComponentNumber The Componen Number for chip select + @param[in] Address The starting byte address for SFDP data read. + @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle + @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ_SFDP) ( + IN PCH_SPI_PROTOCOL *This, + IN UINT8 ComponentNumber, + IN UINT32 Address, + IN UINT32 ByteCount, + OUT UINT8 *SfdpData + ); + +/** + Read Jedec Id from the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] ComponentNumber The Componen Number for chip select + @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically + @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ_JEDEC_ID) ( + IN PCH_SPI_PROTOCOL *This, + IN UINT8 ComponentNumber, + IN UINT32 ByteCount, + OUT UINT8 *JedecId + ); + +/** + Write the status register in the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically + @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_WRITE_STATUS) ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 ByteCount, + IN UINT8 *StatusValue + ); + +/** + Read status register in the flash part. + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically + @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ_STATUS) ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 ByteCount, + OUT UINT8 *StatusValue + ); + +/** + Get the SPI region base and size, based on the enum type + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor. + @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base + @param[out] RegionSize The size for the Region 'n' + + @retval EFI_SUCCESS Read success + @retval EFI_INVALID_PARAMETER Invalid region type given + @retval EFI_DEVICE_ERROR The region is not used +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_GET_REGION_ADDRESS) ( + IN PCH_SPI_PROTOCOL *This, + IN FLASH_REGION_TYPE FlashRegionType, + OUT UINT32 *BaseAddress, + OUT UINT32 *RegionSize + ); + +/** + Read PCH Soft Strap Values + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA. + @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle + @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value. + If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_READ_PCH_SOFTSTRAP) ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 SoftStrapAddr, + IN UINT32 ByteCount, + OUT VOID *SoftStrapValue + ); + +/** + Read CPU Soft Strap Values + + @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. + @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA. + @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle. + @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value. + If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_READ_CPU_SOFTSTRAP) ( + IN PCH_SPI_PROTOCOL *This, + IN UINT32 SoftStrapAddr, + IN UINT32 ByteCount, + OUT VOID *SoftStrapValue + ); + +/** + These protocols/PPI allows a platform module to perform SPI operations through the + Intel PCH SPI Host Controller Interface. +**/ +struct _PCH_SPI_PROTOCOL { + /** + This member specifies the revision of this structure. This field is used to + indicate backwards compatible changes to the protocol. + **/ + UINT8 Revision; + PCH_SPI_FLASH_READ FlashRead; ///< Read data from the flash part. + PCH_SPI_FLASH_WRITE FlashWrite; ///< Write data to the flash part. Remark: Erase may be needed before write to the flash part. + PCH_SPI_FLASH_ERASE FlashErase; ///< Erase some area on the flash part. + PCH_SPI_FLASH_READ_SFDP FlashReadSfdp; ///< Read SFDP data from the flash part. + PCH_SPI_FLASH_READ_JEDEC_ID FlashReadJedecId; ///< Read Jedec Id from the flash part. + PCH_SPI_FLASH_WRITE_STATUS FlashWriteStatus; ///< Write the status register in the flash part. + PCH_SPI_FLASH_READ_STATUS FlashReadStatus; ///< Read status register in the flash part. + PCH_SPI_GET_REGION_ADDRESS GetRegionAddress; ///< Get the SPI region base and size + PCH_SPI_READ_PCH_SOFTSTRAP ReadPchSoftStrap; ///< Read PCH Soft Strap Values + PCH_SPI_READ_CPU_SOFTSTRAP ReadCpuSoftStrap; ///< Read CPU Soft Strap Values +}; + +/** + PCH SPI PPI/PROTOCOL revision number + + Revision 1: Initial version +**/ +#define PCH_SPI_SERVICES_REVISION 1 + +#endif diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index 3b7c3a1a1e..62e3406436 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -78,6 +78,11 @@ gEdkiiVTdNullRootEntryTableGuid = { 0x3de0593f, 0x6e3e, 0x4542, { 0xa1, 0xcb, 0xcb, 0xb2, 0xdb, 0xeb, 0xd8, 0xff } } [Protocols] + ## Protocols that provide services for the Intel(R) PCH SPI Host Controller Compatibility Interface + # Include/Protocol/Spi.h + gPchSpiProtocolGuid = { 0xe007dec0, 0xccc3, 0x4c90, { 0x9c, 0xd0, 0xef, 0x99, 0x38, 0x83, 0x28, 0xcf } } + gPchSmmSpiProtocolGuid = { 0x4840e48e, 0xc264, 0x4fef, { 0xb9, 0x34, 0x14, 0x84, 0x0c, 0x95, 0xd8, 0x3f } } + gEdkiiPlatformVTdPolicyProtocolGuid = { 0x3d17e448, 0x466, 0x4e20, { 0x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }} ## Protocol for device security policy. From 07c4a39812b454eecf1d677fb7894a7b0438f8fb Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 13:42:42 -0700 Subject: [PATCH 07/26] IntelSiliconPkg: Add SpiFlashCommonLib REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 Adds the SpiFlashCommonLib interface to IntelSiliconPkg. The initial library instance added in this change is the NULL instance. Cc: Ray Ni Cc: Rangasai V Chaganty Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone Reviewed-by: Sai Chaganty --- .../Include/Library/SpiFlashCommonLib.h | 98 +++++++++++++++++ IntelSiliconPkg/IntelSiliconPkg.dec | 4 + IntelSiliconPkg/IntelSiliconPkg.dsc | 1 + .../SpiFlashCommonLibNull.c | 101 ++++++++++++++++++ .../SpiFlashCommonLibNull.inf | 28 +++++ 5 files changed, 232 insertions(+) create mode 100644 IntelSiliconPkg/Include/Library/SpiFlashCommonLib.h create mode 100644 IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.c create mode 100644 IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf diff --git a/IntelSiliconPkg/Include/Library/SpiFlashCommonLib.h b/IntelSiliconPkg/Include/Library/SpiFlashCommonLib.h new file mode 100644 index 0000000000..d72b21a380 --- /dev/null +++ b/IntelSiliconPkg/Include/Library/SpiFlashCommonLib.h @@ -0,0 +1,98 @@ +/** @file + The header file includes the common header files, defines + internal structure and functions used by SpiFlashCommonLib. + + Copyright (c) 2019 Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __SPI_FLASH_COMMON_LIB_H__ +#define __SPI_FLASH_COMMON_LIB_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SECTOR_SIZE_4KB 0x1000 // Common 4kBytes sector size +/** + Enable block protection on the Serial Flash device. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashLock ( + VOID + ); + +/** + Read NumBytes bytes of data from the address specified by + PAddress into Buffer. + + @param[in] Address The starting physical address of the read. + @param[in,out] NumBytes On input, the number of bytes to read. On output, the number + of bytes actually read. + @param[out] Buffer The destination data buffer for the read. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashRead ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + OUT UINT8 *Buffer + ); + +/** + Write NumBytes bytes of data from Buffer to the address specified by + PAddresss. + + @param[in] Address The starting physical address of the write. + @param[in,out] NumBytes On input, the number of bytes to write. On output, + the actual number of bytes written. + @param[in] Buffer The source data buffer for the write. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashWrite ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + IN UINT8 *Buffer + ); + +/** + Erase the block starting at Address. + + @param[in] Address The starting physical address of the block to be erased. + This library assume that caller garantee that the PAddress + is at the starting address of this block. + @param[in] NumBytes On input, the number of bytes of the logical block to be erased. + On output, the actual number of bytes erased. + + @retval EFI_SUCCESS. Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashBlockErase ( + IN UINTN Address, + IN UINTN *NumBytes + ); + +#endif diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index 62e3406436..a70f9e1cd8 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -46,6 +46,10 @@ # ReportCpuHobLib|Include/Library/ReportCpuHobLib.h + ## @libraryclass Provides services to perform SPI flash actions + # + SpiFlashCommonLib|Include/Library/SpiFlashCommonLib.h + [Guids] ## GUID for Package token space # {A9F8D54E-1107-4F0A-ADD0-4587E7A4A735} diff --git a/IntelSiliconPkg/IntelSiliconPkg.dsc b/IntelSiliconPkg/IntelSiliconPkg.dsc index ffb7237d1d..d426c2f2fb 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dsc +++ b/IntelSiliconPkg/IntelSiliconPkg.dsc @@ -94,6 +94,7 @@ IntelSiliconPkg/Library/PeiDxeSmmBootMediaLib/DxeSmmFirmwareBootMediaLib.inf IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf IntelSiliconPkg/Library/ReportCpuHobLib/ReportCpuHobLib.inf + IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf [BuildOptions] *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.c b/IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.c new file mode 100644 index 0000000000..66e1e43594 --- /dev/null +++ b/IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.c @@ -0,0 +1,101 @@ +/** @file + Null Library instance of SPI Flash Common Library Class + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +/** + Enable block protection on the Serial Flash device. + + @retval EFI_SUCCESS Operation is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashLock ( + VOID + ) +{ + return EFI_SUCCESS; +} + +/** + Read NumBytes bytes of data from the address specified by + PAddress into Buffer. + + @param[in] Address The starting physical address of the read. + @param[in,out] NumBytes On input, the number of bytes to read. On output, the number + of bytes actually read. + @param[out] Buffer The destination data buffer for the read. + + @retval EFI_SUCCESS Operation is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashRead ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + OUT UINT8 *Buffer + ) +{ + ASSERT(FALSE); + return EFI_SUCCESS; +} + +/** + Write NumBytes bytes of data from Buffer to the address specified by + PAddresss. + + @param[in] Address The starting physical address of the write. + @param[in,out] NumBytes On input, the number of bytes to write. On output, + the actual number of bytes written. + @param[in] Buffer The source data buffer for the write. + + @retval EFI_SUCCESS Operation is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashWrite ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + IN UINT8 *Buffer + ) +{ + ASSERT(FALSE); + return EFI_SUCCESS; +} + +/** + Erase the block starting at Address. + + @param[in] Address The starting physical address of the block to be erased. + This library assume that caller guarantee that the PAddress + is at the starting address of this block. + @param[in] NumBytes On input, the number of bytes of the logical block to be erased. + On output, the actual number of bytes erased. + + @retval EFI_SUCCESS. Operation is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashBlockErase ( + IN UINTN Address, + IN UINTN *NumBytes + ) +{ + ASSERT(FALSE); + return EFI_SUCCESS; +} diff --git a/IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf b/IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf new file mode 100644 index 0000000000..37f27dbff3 --- /dev/null +++ b/IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf @@ -0,0 +1,28 @@ +### @file +# NULL instance of Spi Flash Common Library Class +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + +[Defines] + INF_VERSION = 0x00010017 + BASE_NAME = SpiFlashCommonLibNull + FILE_GUID = F35BBEE7-A681-443E-BB15-07AF9FABBDED + VERSION_STRING = 1.0 + MODULE_TYPE = BASE + LIBRARY_CLASS = SpiFlashCommonLib +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Packages] + MdePkg/MdePkg.dec + IntelSiliconPkg/IntelSiliconPkg.dec + +[Sources] + SpiFlashCommonLibNull.c From fe4e0c5fbf0d76ce6ea122ac69dfa8b866cf3ff5 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 13:42:43 -0700 Subject: [PATCH 08/26] IntelSiliconPkg: Add SmmSpiFlashCommonLib REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 Adds the SMM instance of SpiFlashCommonLib. The code is based on refactoring existing library instances into a consolidated version with no functional impact. Cc: Ray Ni Cc: Rangasai V Chaganty Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone Reviewed-by: Sai Chaganty --- IntelSiliconPkg/IntelSiliconPkg.dsc | 5 + .../SmmSpiFlashCommonLib.c | 58 +++++ .../SmmSpiFlashCommonLib.inf | 48 ++++ .../SmmSpiFlashCommonLib/SpiFlashCommon.c | 209 ++++++++++++++++++ 4 files changed, 320 insertions(+) create mode 100644 IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c create mode 100644 IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf create mode 100644 IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c diff --git a/IntelSiliconPkg/IntelSiliconPkg.dsc b/IntelSiliconPkg/IntelSiliconPkg.dsc index d426c2f2fb..a4cd4b2e22 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dsc +++ b/IntelSiliconPkg/IntelSiliconPkg.dsc @@ -59,6 +59,10 @@ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf +[LibraryClasses.common.DXE_SMM_DRIVER] + MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf + SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf + ################################################################################################### # # Components Section - list of the modules and components that will be processed by compilation @@ -95,6 +99,7 @@ IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf IntelSiliconPkg/Library/ReportCpuHobLib/ReportCpuHobLib.inf IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf + IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf [BuildOptions] *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES diff --git a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c new file mode 100644 index 0000000000..689e54ed8e --- /dev/null +++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c @@ -0,0 +1,58 @@ +/** @file + SMM Library instance of SPI Flash Common Library Class + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +extern PCH_SPI_PROTOCOL *mSpiProtocol; + +extern UINTN mBiosAreaBaseAddress; +extern UINTN mBiosSize; +extern UINTN mBiosOffset; + +/** + The library constructuor. + + The function does the necessary initialization work for this library + instance. + + @param[in] ImageHandle The firmware allocated handle for the UEFI image. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS The function always return EFI_SUCCESS for now. + It will ASSERT on error for debug version. + @retval EFI_ERROR Please reference LocateProtocol for error code details. +**/ +EFI_STATUS +EFIAPI +SmmSpiFlashCommonLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINT32 BaseAddr; + UINT32 RegionSize; + + mBiosAreaBaseAddress = (UINTN)PcdGet32 (PcdBiosAreaBaseAddress); + mBiosSize = (UINTN)PcdGet32 (PcdBiosSize); + + // + // Locate the SMM SPI protocol. + // + Status = gSmst->SmmLocateProtocol ( + &gPchSmmSpiProtocolGuid, + NULL, + (VOID **) &mSpiProtocol + ); + ASSERT_EFI_ERROR (Status); + + mSpiProtocol->GetRegionAddress (mSpiProtocol, FlashRegionBios, &BaseAddr, &RegionSize); + mBiosOffset = BaseAddr; + return Status; +} diff --git a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf new file mode 100644 index 0000000000..5f36742137 --- /dev/null +++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf @@ -0,0 +1,48 @@ +## @file +# SMM Library instance of Spi Flash Common Library Class +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010017 + BASE_NAME = SmmSpiFlashCommonLib + FILE_GUID = 99721728-C39D-4600-BD38-71E8238FEEF2 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_SMM_DRIVER + LIBRARY_CLASS = SpiFlashCommonLib|DXE_SMM_DRIVER + CONSTRUCTOR = SmmSpiFlashCommonLibConstructor +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + IoLib + MemoryAllocationLib + SmmServicesTableLib + UefiLib + +[Packages] + MdePkg/MdePkg.dec + IntelSiliconPkg/IntelSiliconPkg.dec + +[Pcd] + gIntelSiliconPkgTokenSpaceGuid.PcdBiosAreaBaseAddress ## CONSUMES + gIntelSiliconPkgTokenSpaceGuid.PcdBiosSize ## CONSUMES + +[Sources] + SmmSpiFlashCommonLib.c + SpiFlashCommon.c + +[Protocols] + gPchSmmSpiProtocolGuid ## CONSUMES + +[Depex.X64.DXE_SMM_DRIVER] + gPchSmmSpiProtocolGuid diff --git a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c new file mode 100644 index 0000000000..39f223a1ab --- /dev/null +++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c @@ -0,0 +1,209 @@ +/** @file + Wrap PCH_SPI_PROTOCOL to provide some library level interfaces + for module use. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include + +PCH_SPI_PROTOCOL *mSpiProtocol; + +// +// Variables for boottime and runtime usage. +// +UINTN mBiosAreaBaseAddress = 0; +UINTN mBiosSize = 0; +UINTN mBiosOffset = 0; + +/** + Enable block protection on the Serial Flash device. + + @retval EFI_SUCCESS Opertion is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashLock ( + VOID + ) +{ + return EFI_SUCCESS; +} + +/** + Read NumBytes bytes of data from the address specified by + PAddress into Buffer. + + @param[in] Address The starting physical address of the read. + @param[in,out] NumBytes On input, the number of bytes to read. On output, the number + of bytes actually read. + @param[out] Buffer The destination data buffer for the read. + + @retval EFI_SUCCESS Operation is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + +**/ +EFI_STATUS +EFIAPI +SpiFlashRead ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + OUT UINT8 *Buffer + ) +{ + ASSERT ((NumBytes != NULL) && (Buffer != NULL)); + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // This function is implemented specifically for those platforms + // at which the SPI device is memory mapped for read. So this + // function just do a memory copy for Spi Flash Read. + // + CopyMem (Buffer, (VOID *) Address, *NumBytes); + + return EFI_SUCCESS; +} + +/** + Write NumBytes bytes of data from Buffer to the address specified by + PAddresss. + + @param[in] Address The starting physical address of the write. + @param[in,out] NumBytes On input, the number of bytes to write. On output, + the actual number of bytes written. + @param[in] Buffer The source data buffer for the write. + + @retval EFI_SUCCESS Operation is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +EFIAPI +SpiFlashWrite ( + IN UINTN Address, + IN OUT UINT32 *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINT32 Length; + UINT32 RemainingBytes; + + ASSERT ((NumBytes != NULL) && (Buffer != NULL)); + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + ASSERT (Address >= mBiosAreaBaseAddress); + if (Address < mBiosAreaBaseAddress) { + return EFI_INVALID_PARAMETER; + } + + Offset = Address - mBiosAreaBaseAddress; + + ASSERT ((*NumBytes + Offset) <= mBiosSize); + if ((*NumBytes + Offset) > mBiosSize) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + RemainingBytes = *NumBytes; + + + while (RemainingBytes > 0) { + if (RemainingBytes > SECTOR_SIZE_4KB) { + Length = SECTOR_SIZE_4KB; + } else { + Length = RemainingBytes; + } + Status = mSpiProtocol->FlashWrite ( + mSpiProtocol, + FlashRegionBios, + (UINT32) Offset, + Length, + Buffer + ); + if (EFI_ERROR (Status)) { + break; + } + RemainingBytes -= Length; + Offset += Length; + Buffer += Length; + } + + // + // Actual number of bytes written + // + *NumBytes -= RemainingBytes; + + return Status; +} + +/** + Erase the block starting at Address. + + @param[in] Address The starting physical address of the block to be erased. + This library assume that caller garantee that the PAddress + is at the starting address of this block. + @param[in] NumBytes On input, the number of bytes of the logical block to be erased. + On output, the actual number of bytes erased. + + @retval EFI_SUCCESS. Operation is successful. + @retval EFI_DEVICE_ERROR If there is any device errors. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +EFIAPI +SpiFlashBlockErase ( + IN UINTN Address, + IN UINTN *NumBytes + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINTN RemainingBytes; + + ASSERT (NumBytes != NULL); + if (NumBytes == NULL) { + return EFI_INVALID_PARAMETER; + } + + ASSERT (Address >= mBiosAreaBaseAddress); + if (Address < mBiosAreaBaseAddress) { + return EFI_INVALID_PARAMETER; + } + + Offset = Address - mBiosAreaBaseAddress; + + ASSERT ((*NumBytes % SECTOR_SIZE_4KB) == 0); + if ((*NumBytes % SECTOR_SIZE_4KB) != 0) { + return EFI_INVALID_PARAMETER; + } + + ASSERT ((*NumBytes + Offset) <= mBiosSize); + if ((*NumBytes + Offset) > mBiosSize) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + RemainingBytes = *NumBytes; + + + Status = mSpiProtocol->FlashErase ( + mSpiProtocol, + FlashRegionBios, + (UINT32) Offset, + (UINT32) RemainingBytes + ); + return Status; +} From 84033fe9fda359911f6ec903b45ca4415fb4e301 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 13:42:44 -0700 Subject: [PATCH 09/26] IntelSiliconPkg: Add MM SPI FVB services REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 Adds a Traditional MM and Standalone MM SPI FVB Service driver to IntelSiliconPkg. These drivers produce the firmware volume block protocol for SPI flash devices compliant with the Intel Serial Flash Interface Compatibility Specification. Cc: Ray Ni Cc: Rangasai V Chaganty Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone --- .../Feature/Flash/SpiFvbService/FvbInfo.c | 94 ++ .../Flash/SpiFvbService/SpiFvbServiceCommon.c | 903 ++++++++++++++++++ .../Flash/SpiFvbService/SpiFvbServiceCommon.h | 158 +++ .../Flash/SpiFvbService/SpiFvbServiceMm.c | 271 ++++++ .../Flash/SpiFvbService/SpiFvbServiceMm.h | 22 + .../Flash/SpiFvbService/SpiFvbServiceSmm.inf | 68 ++ .../SpiFvbService/SpiFvbServiceStandaloneMm.c | 32 + .../SpiFvbServiceStandaloneMm.inf | 67 ++ .../SpiFvbServiceTraditionalMm.c | 32 + IntelSiliconPkg/IntelSiliconPkg.dsc | 11 + 10 files changed, 1658 insertions(+) create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.h create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.c create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf create mode 100644 IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceTraditionalMm.c diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c new file mode 100644 index 0000000000..88320e6790 --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c @@ -0,0 +1,94 @@ +/**@file + Defines data structure that is the volume header found. + These data is intent to decouple FVB driver with FV header. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SpiFvbServiceCommon.h" + +#define FIRMWARE_BLOCK_SIZE 0x10000 +#define FVB_MEDIA_BLOCK_SIZE FIRMWARE_BLOCK_SIZE + +#define NV_STORAGE_BASE_ADDRESS FixedPcdGet32(PcdFlashNvStorageVariableBase) +#define SYSTEM_NV_BLOCK_NUM ((FixedPcdGet32(PcdFlashNvStorageVariableSize)+ FixedPcdGet32(PcdFlashNvStorageFtwWorkingSize) + FixedPcdGet32(PcdFlashNvStorageFtwSpareSize))/ FVB_MEDIA_BLOCK_SIZE) + +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_FIRMWARE_VOLUME_HEADER FvbInfo; + EFI_FV_BLOCK_MAP_ENTRY End[1]; +} EFI_FVB2_MEDIA_INFO; + +// +// This data structure contains a template of all correct FV headers, which is used to restore +// Fv header if it's corrupted. +// +EFI_FVB2_MEDIA_INFO mPlatformFvbMediaInfo[] = { + // + // Systen NvStorage FVB + // + { + NV_STORAGE_BASE_ADDRESS, + { + {0,}, //ZeroVector[16] + EFI_SYSTEM_NV_DATA_FV_GUID, + FVB_MEDIA_BLOCK_SIZE * SYSTEM_NV_BLOCK_NUM, + EFI_FVH_SIGNATURE, + 0x0004feff, // check MdePkg/Include/Pi/PiFirmwareVolume.h for details on EFI_FVB_ATTRIBUTES_2 + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, //CheckSum which will be calucated dynamically. + 0, //ExtHeaderOffset + {0,}, //Reserved[1] + 2, //Revision + { + { + SYSTEM_NV_BLOCK_NUM, + FVB_MEDIA_BLOCK_SIZE, + } + } + }, + { + { + 0, + 0 + } + } + } +}; + +EFI_STATUS +GetFvbInfo ( + IN EFI_PHYSICAL_ADDRESS FvBaseAddress, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +{ + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + + for (Index = 0; Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB2_MEDIA_INFO); Index++) { + if (mPlatformFvbMediaInfo[Index].BaseAddress == FvBaseAddress) { + FvHeader = &mPlatformFvbMediaInfo[Index].FvbInfo; + + // + // Update the checksum value of FV header. + // + FvHeader->Checksum = CalculateCheckSum16 ( (UINT16 *) FvHeader, FvHeader->HeaderLength); + + *FvbInfo = FvHeader; + + DEBUG ((DEBUG_INFO, "BaseAddr: 0x%lx \n", FvBaseAddress)); + DEBUG ((DEBUG_INFO, "FvLength: 0x%lx \n", (*FvbInfo)->FvLength)); + DEBUG ((DEBUG_INFO, "HeaderLength: 0x%x \n", (*FvbInfo)->HeaderLength)); + DEBUG ((DEBUG_INFO, "Header Checksum: 0x%X\n", (*FvbInfo)->Checksum)); + DEBUG ((DEBUG_INFO, "FvBlockMap[0].NumBlocks: 0x%x \n", (*FvbInfo)->BlockMap[0].NumBlocks)); + DEBUG ((DEBUG_INFO, "FvBlockMap[0].BlockLength: 0x%x \n", (*FvbInfo)->BlockMap[0].Length)); + DEBUG ((DEBUG_INFO, "FvBlockMap[1].NumBlocks: 0x%x \n", (*FvbInfo)->BlockMap[1].NumBlocks)); + DEBUG ((DEBUG_INFO, "FvBlockMap[1].BlockLength: 0x%x \n\n", (*FvbInfo)->BlockMap[1].Length)); + + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c new file mode 100644 index 0000000000..8e5d6a1f83 --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c @@ -0,0 +1,903 @@ +/** @file + Common driver source for several Serial Flash devices + which are compliant with the Intel(R) Serial Flash Interface Compatibility Specification. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SpiFvbServiceCommon.h" + +// +// Global variable for this FVB driver which contains +// the private data of all firmware volume block instances +// +FVB_GLOBAL mFvbModuleGlobal; + +// +// This platform driver knows there are multiple FVs on FD. +// Now we only provide FVs on Variable region and MicorCode region for performance issue. +// +FV_INFO mPlatformFvBaseAddress[] = { + {0, 0}, // {FixedPcdGet32(PcdFlashNvStorageVariableBase), FixedPcdGet32(PcdFlashNvStorageVariableSize)}, + {0, 0}, // {FixedPcdGet32(PcdFlashMicrocodeFvBase), FixedPcdGet32(PcdFlashMicrocodeFvSize)}, + {0, 0} +}; + +FV_INFO mPlatformDefaultBaseAddress[] = { + {0, 0}, // {FixedPcdGet32(PcdFlashNvStorageVariableBase), FixedPcdGet32(PcdFlashNvStorageVariableSize)}, + {0, 0}, // {FixedPcdGet32(PcdFlashMicrocodeFvBase), FixedPcdGet32(PcdFlashMicrocodeFvSize)}, + {0, 0} +}; + +FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), + (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) + } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS) 0, + (EFI_PHYSICAL_ADDRESS) 0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = { + { + { + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + { + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)), + (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8) + } + }, + { 0 } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } + } +}; + +// +// Template structure used when installing FVB protocol +// +EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL mFvbProtocolTemplate = { + FvbProtocolGetAttributes, + FvbProtocolSetAttributes, + FvbProtocolGetPhysicalAddress, + FvbProtocolGetBlockSize, + FvbProtocolRead, + FvbProtocolWrite, + FvbProtocolEraseBlocks, + NULL +}; + +/** + Get the EFI_FVB_ATTRIBUTES_2 of a FV. + + @param[in] FvbInstance The pointer to the EFI_FVB_INSTANCE. + + @return Attributes of the FV identified by FvbInstance. + +**/ +EFI_FVB_ATTRIBUTES_2 +FvbGetVolumeAttributes ( + IN EFI_FVB_INSTANCE *FvbInstance + ) +{ + return FvbInstance->FvHeader.Attributes; +} + +/** + Retrieves the starting address of an LBA in an FV. It also + return a few other attribut of the FV. + + @param[in] FvbInstance The pointer to the EFI_FVB_INSTANCE. + @param[in] Lba The logical block address + @param[out] LbaAddress On output, contains the physical starting address + of the Lba + @param[out] LbaLength On output, contains the length of the block + @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + + @retval EFI_SUCCESS Successfully returns + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbGetLbaAddress ( + IN EFI_FVB_INSTANCE *FvbInstance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks + ) +{ + UINT32 NumBlocks; + UINT32 BlockLength; + UINTN Offset; + EFI_LBA StartLba; + EFI_LBA NextLba; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + + StartLba = 0; + Offset = 0; + BlockMap = &(FvbInstance->FvHeader.BlockMap[0]); + + // + // Parse the blockmap of the FV to find which map entry the Lba belongs to + // + while (TRUE) { + NumBlocks = BlockMap->NumBlocks; + BlockLength = BlockMap->Length; + + if ( NumBlocks == 0 || BlockLength == 0) { + return EFI_INVALID_PARAMETER; + } + + NextLba = StartLba + NumBlocks; + + // + // The map entry found + // + if (Lba >= StartLba && Lba < NextLba) { + Offset = Offset + (UINTN)MultU64x32((Lba - StartLba), BlockLength); + if (LbaAddress ) { + *LbaAddress = FvbInstance->FvBase + Offset; + } + + if (LbaLength ) { + *LbaLength = BlockLength; + } + + if (NumOfBlocks ) { + *NumOfBlocks = (UINTN)(NextLba - Lba); + } + return EFI_SUCCESS; + } + + StartLba = NextLba; + Offset = Offset + NumBlocks * BlockLength; + BlockMap++; + } +} + +/** + Reads specified number of bytes into a buffer from the specified block. + + @param[in] FvbInstance The pointer to the EFI_FVB_INSTANCE + @param[in] Lba The logical block address to be read from + @param[in] BlockOffset Offset into the block at which to begin reading + @param[in] NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + @param[in] Buffer Pointer to a caller allocated buffer that will be + used to hold the data read + + + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be read + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL + +**/ +EFI_STATUS +FvbReadBlock ( + IN EFI_FVB_INSTANCE *FvbInstance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + BOOLEAN BadBufferSize = FALSE; + + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (FvbInstance, Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR(Status)) { + return Status; + } + + Attributes = FvbGetVolumeAttributes (FvbInstance); + + if ((Attributes & EFI_FVB2_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + DEBUG ((DEBUG_INFO, + "FvReadBlock: Reducing Numbytes from 0x%x to 0x%x\n", + *NumBytes, + (UINT32)(LbaLength - BlockOffset)) + ); + *NumBytes = (UINT32) (LbaLength - BlockOffset); + BadBufferSize = TRUE; + } + + Status = SpiFlashRead (LbaAddress + BlockOffset, (UINT32 *)NumBytes, Buffer); + + if (!EFI_ERROR (Status) && BadBufferSize) { + return EFI_BAD_BUFFER_SIZE; + } else { + return Status; + } +} + +/** + Writes specified number of bytes from the input buffer to the block. + + @param[in] FvbInstance The pointer to the EFI_FVB_INSTANCE + @param[in] Lba The starting logical block index to write to + @param[in] BlockOffset Offset into the block at which to begin writing + @param[in] NumBytes Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + @param[in] Buffer Pointer to a caller allocated buffer that contains + the source for the write + @retval EFI_SUCCESS The firmware volume was written successfully + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be written + @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL + +**/ +EFI_STATUS +FvbWriteBlock ( + IN EFI_FVB_INSTANCE *FvbInstance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + BOOLEAN BadBufferSize = FALSE; + + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (FvbInstance, Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Check if the FV is write enabled + // + Attributes = FvbGetVolumeAttributes (FvbInstance); + if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + // + // Perform boundary checks and adjust NumBytes + // + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + DEBUG ((DEBUG_INFO, + "FvWriteBlock: Reducing Numbytes from 0x%x to 0x%x\n", + *NumBytes, + (UINT32)(LbaLength - BlockOffset)) + ); + *NumBytes = (UINT32) (LbaLength - BlockOffset); + BadBufferSize = TRUE; + } + + Status = SpiFlashWrite (LbaAddress + BlockOffset, (UINT32 *)NumBytes, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SpiFlashLock (); + if (EFI_ERROR (Status)) { + return Status; + } + + WriteBackInvalidateDataCacheRange ((VOID *) (LbaAddress + BlockOffset), *NumBytes); + + if (!EFI_ERROR (Status) && BadBufferSize) { + return EFI_BAD_BUFFER_SIZE; + } else { + return Status; + } +} + + + +/** + Erases and initializes a firmware volume block. + + @param[in] FvbInstance The pointer to the EFI_FVB_INSTANCE + @param[in] Lba The logical block index to be erased + + @retval EFI_SUCCESS The erase request was successfully completed + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + @retval EFI_INVALID_PARAMETER Instance not found + +**/ +EFI_STATUS +FvbEraseBlock ( + IN EFI_FVB_INSTANCE *FvbInstance, + IN EFI_LBA Lba + ) +{ + + EFI_FVB_ATTRIBUTES_2 Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check if the FV is write enabled + // + Attributes = FvbGetVolumeAttributes (FvbInstance); + + if( (Attributes & EFI_FVB2_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + // + // Get the starting address of the block for erase. + // + Status = FvbGetLbaAddress (FvbInstance, Lba, &LbaAddress, &LbaLength, NULL); + if (EFI_ERROR(Status)) { + return Status; + } + + Status = SpiFlashBlockErase (LbaAddress, &LbaLength); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = SpiFlashLock (); + if (EFI_ERROR (Status)) { + return Status; + } + + WriteBackInvalidateDataCacheRange ((VOID *) LbaAddress, LbaLength); + + return Status; +} + +/** + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + + @param[in] FvbInstance The pointer to the EFI_FVB_INSTANCE. + @param[in] Attributes On input, it is a pointer to EFI_FVB_ATTRIBUTES_2 + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + + @retval EFI_SUCCESS Successfully returns + @retval EFI_ACCESS_DENIED The volume setting is locked and cannot be modified + @retval EFI_INVALID_PARAMETER Instance not found, or The attributes requested are + in conflict with the capabilities as declared in the + firmware volume header + +**/ +EFI_STATUS +FvbSetVolumeAttributes ( + IN EFI_FVB_INSTANCE *FvbInstance, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FVB_ATTRIBUTES_2 OldAttributes; + EFI_FVB_ATTRIBUTES_2 *AttribPtr; + EFI_FVB_ATTRIBUTES_2 UnchangedAttributes; + UINT32 Capabilities; + UINT32 OldStatus, NewStatus; + + AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) &(FvbInstance->FvHeader.Attributes); + OldAttributes = *AttribPtr; + Capabilities = OldAttributes & EFI_FVB2_CAPABILITIES; + OldStatus = OldAttributes & EFI_FVB2_STATUS; + NewStatus = *Attributes & EFI_FVB2_STATUS; + + UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP | \ + EFI_FVB2_STICKY_WRITE | \ + EFI_FVB2_MEMORY_MAPPED | \ + EFI_FVB2_ERASE_POLARITY | \ + EFI_FVB2_READ_LOCK_CAP | \ + EFI_FVB2_WRITE_LOCK_CAP | \ + EFI_FVB2_ALIGNMENT; + + // + // Some attributes of FV is read only can *not* be set + // + if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) { + return EFI_INVALID_PARAMETER; + } + + // + // If firmware volume is locked, no status bit can be updated + // + if ( OldAttributes & EFI_FVB2_LOCK_STATUS ) { + if ( OldStatus ^ NewStatus ) { + return EFI_ACCESS_DENIED; + } + } + + // + // Test read disable + // + if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test read enable + // + if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB2_READ_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write disable + // + if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test write enable + // + if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB2_WRITE_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Test lock + // + if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) { + if (NewStatus & EFI_FVB2_LOCK_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS)); + *AttribPtr = (*AttribPtr) | NewStatus; + *Attributes = *AttribPtr; + + return EFI_SUCCESS; +} + +/** + Check the integrity of firmware volume header + + @param[in] FvHeader A pointer to a firmware volume header + + @retval TRUE The firmware volume is consistent + @retval FALSE The firmware volume has corrupted. + +**/ +BOOLEAN +IsFvHeaderValid ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN CONST EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +{ + if (FvBase == PcdGet32(PcdFlashNvStorageVariableBase)) { + if (CompareMem (&FvHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof(EFI_GUID)) != 0 ) { + return FALSE; + } + } else { + if (CompareMem (&FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) { + return FALSE; + } + } + if ( (FvHeader->Revision != EFI_FVH_REVISION) || + (FvHeader->Signature != EFI_FVH_SIGNATURE) || + (FvHeader->FvLength == ((UINTN) -1)) || + ((FvHeader->HeaderLength & 0x01 ) !=0) ) { + return FALSE; + } + + if (CalculateCheckSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength) != 0) { + return FALSE; + } + + return TRUE; +} + +// +// FVB protocol APIs +// + +/** + Retrieves the physical address of the device. + + @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL. + @param[out] Address Output buffer containing the address. + + retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +{ + EFI_FVB_INSTANCE *FvbInstance; + + FvbInstance = FVB_INSTANCE_FROM_THIS (This); + + *Address = FvbInstance->FvBase; + + return EFI_SUCCESS; +} + +/** + Retrieve the size of a logical block + + @param[in] This Calling context + @param[in] Lba Indicates which block to return the size for. + @param[out] BlockSize A pointer to a caller allocated UINTN in which + the size of the block is returned + @param[out] NumOfBlocks A pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +{ + EFI_FVB_INSTANCE *FvbInstance; + + FvbInstance = FVB_INSTANCE_FROM_THIS (This); + + DEBUG((DEBUG_INFO, + "FvbProtocolGetBlockSize: Lba: 0x%lx BlockSize: 0x%x NumOfBlocks: 0x%x\n", + Lba, + BlockSize, + NumOfBlocks) + ); + + return FvbGetLbaAddress ( + FvbInstance, + Lba, + NULL, + BlockSize, + NumOfBlocks + ); +} + +/** + Retrieves Volume attributes. No polarity translations are done. + + @param[in] This Calling context + @param[out] Attributes Output buffer which contains attributes + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_FVB_INSTANCE *FvbInstance; + + FvbInstance = FVB_INSTANCE_FROM_THIS (This); + + *Attributes = FvbGetVolumeAttributes (FvbInstance); + + DEBUG ((DEBUG_INFO, + "FvbProtocolGetAttributes: This: 0x%x Attributes: 0x%x\n", + This, + *Attributes) + ); + + return EFI_SUCCESS; +} + +/** + Sets Volume attributes. No polarity translations are done. + + @param[in] This Calling context + @param[out] Attributes Output buffer which contains attributes + + @retval EFI_SUCCESS The function always return successfully. + +**/ +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ) +{ + EFI_STATUS Status; + EFI_FVB_INSTANCE *FvbInstance; + + DEBUG((DEBUG_INFO, + "FvbProtocolSetAttributes: Before SET - This: 0x%x Attributes: 0x%x\n", + This, + *Attributes) + ); + + FvbInstance = FVB_INSTANCE_FROM_THIS (This); + + Status = FvbSetVolumeAttributes (FvbInstance, Attributes); + + DEBUG((DEBUG_INFO, + "FvbProtocolSetAttributes: After SET - This: 0x%x Attributes: 0x%x\n", + This, + *Attributes) + ); + + return Status; +} + +/** + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be verified + prior to erasing any blocks. If a block is requested that does not exist + within the associated firmware volume (it has a larger index than the last + block of the firmware volume), the EraseBlock() function must return + EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. + + @param[in] This Calling context + @param[in] ... Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. + + @retval EFI_SUCCESS The erase request was successfully completed + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + +**/ +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +{ + EFI_FVB_INSTANCE *FvbInstance; + UINTN NumOfBlocks; + VA_LIST Args; + EFI_LBA StartingLba; + UINTN NumOfLba; + EFI_STATUS Status; + + DEBUG((DEBUG_INFO, "FvbProtocolEraseBlocks: \n")); + + FvbInstance = FVB_INSTANCE_FROM_THIS (This); + + NumOfBlocks = FvbInstance->NumOfBlocks; + + VA_START (Args, This); + + do { + StartingLba = VA_ARG (Args, EFI_LBA); + if ( StartingLba == EFI_LBA_LIST_TERMINATOR ) { + break; + } + + NumOfLba = VA_ARG (Args, UINT32); + + // + // Check input parameters + // + if (NumOfLba == 0) { + VA_END (Args); + return EFI_INVALID_PARAMETER; + } + + if ( ( StartingLba + NumOfLba ) > NumOfBlocks ) { + return EFI_INVALID_PARAMETER; + } + } while ( 1 ); + + VA_END (Args); + + VA_START (Args, This); + do { + StartingLba = VA_ARG (Args, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba = VA_ARG (Args, UINT32); + + while ( NumOfLba > 0 ) { + Status = FvbEraseBlock (FvbInstance, StartingLba); + if ( EFI_ERROR(Status)) { + VA_END (Args); + return Status; + } + StartingLba ++; + NumOfLba --; + } + + } while ( 1 ); + + VA_END (Args); + + return EFI_SUCCESS; +} + +/** + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + @param[in] This Calling context + @param[in] Lba Block in which to begin write + @param[in] Offset Offset in the block at which to begin write + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS The firmware volume was written successfully + @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written + @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be written + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL + +**/ +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +{ + EFI_FVB_INSTANCE *FvbInstance; + + FvbInstance = FVB_INSTANCE_FROM_THIS (This); + + DEBUG((DEBUG_INFO, + "FvbProtocolWrite: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n", + Lba, + Offset, + *NumBytes, + Buffer) + ); + + return FvbWriteBlock (FvbInstance, Lba, Offset, NumBytes, Buffer); +} + +/** + Reads data beginning at Lba:Offset from FV. The Read terminates either + when *NumBytes of data have been read, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + + @param[in] This Calling context + @param[in] Lba Block in which to begin write + @param[in] Offset Offset in the block at which to begin write + @param[in,out] NumBytes On input, indicates the requested write size. On + output, indicates the actual number of bytes written + @param[in] Buffer Buffer containing source data for the write. + + @retval EFI_SUCCESS The firmware volume was read successfully and + contents are in Buffer + @retval EFI_BAD_BUFFER_SIZE Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer + @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state + @retval EFI_DEVICE_ERROR The block device is not functioning correctly and + could not be read + @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL + +**/ +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ) +{ + EFI_FVB_INSTANCE *FvbInstance; + EFI_STATUS Status; + + FvbInstance = FVB_INSTANCE_FROM_THIS (This); + Status = FvbReadBlock (FvbInstance, Lba, Offset, NumBytes, Buffer); + DEBUG((DEBUG_INFO, + "FvbProtocolRead: Lba: 0x%lx Offset: 0x%x NumBytes: 0x%x, Buffer: 0x%x\n", + Lba, + Offset, + *NumBytes, + Buffer) + ); + + return Status; +} diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h new file mode 100644 index 0000000000..6f7ae0648a --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h @@ -0,0 +1,158 @@ +/** @file + Common source definitions used in serial flash drivers + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SPI_FVB_SERVICE_COMMON_H +#define _SPI_FVB_SERVICE_COMMON_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// +// Define two helper macro to extract the Capability field or Status field in FVB +// bit fields +// +#define EFI_FVB2_CAPABILITIES (EFI_FVB2_READ_DISABLED_CAP | \ + EFI_FVB2_READ_ENABLED_CAP | \ + EFI_FVB2_WRITE_DISABLED_CAP | \ + EFI_FVB2_WRITE_ENABLED_CAP | \ + EFI_FVB2_LOCK_CAP \ + ) + +#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS) + +#define FVB_INSTANCE_SIGNATURE SIGNATURE_32('F','V','B','I') + +typedef struct { + UINT32 Signature; + UINTN FvBase; + UINTN NumOfBlocks; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FvbProtocol; + EFI_FIRMWARE_VOLUME_HEADER FvHeader; +} EFI_FVB_INSTANCE; + +typedef struct { + EFI_FVB_INSTANCE *FvbInstance; + UINT32 NumFv; +} FVB_GLOBAL; + +// +// Fvb Protocol instance data +// +#define FVB_INSTANCE_FROM_THIS(a) CR(a, EFI_FVB_INSTANCE, FvbProtocol, FVB_INSTANCE_SIGNATURE) + +typedef struct { + MEDIA_FW_VOL_DEVICE_PATH FvDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_PIWG_DEVICE_PATH; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_MEMMAP_DEVICE_PATH; + +typedef struct { + UINT32 FvBase; + UINT32 FvSize; +} FV_INFO; + +// +// Protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes + ); + +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ); + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ); + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ); + +BOOLEAN +IsFvHeaderValid ( + IN EFI_PHYSICAL_ADDRESS FvBase, + IN CONST EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ); + +EFI_STATUS +GetFvbInfo ( + IN EFI_PHYSICAL_ADDRESS FvBaseAddress, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ); + +extern FVB_GLOBAL mFvbModuleGlobal; +extern FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate; +extern FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate; +extern EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL mFvbProtocolTemplate; +extern FV_INFO mPlatformFvBaseAddress[]; +extern FV_INFO mPlatformDefaultBaseAddress[]; + +#endif diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c new file mode 100644 index 0000000000..835c212086 --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c @@ -0,0 +1,271 @@ +/** @file + MM driver source for several Serial Flash devices + which are compliant with the Intel(R) Serial Flash Interface Compatibility Specification. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SpiFvbServiceCommon.h" +#include +#include +#include + +/** + The function installs EFI_FIRMWARE_VOLUME_BLOCK protocol + for each FV in the system. + + @param[in] FvbInstance The pointer to a FW volume instance structure, + which contains the information about one FV. + + @retval VOID + +**/ +VOID +InstallFvbProtocol ( + IN EFI_FVB_INSTANCE *FvbInstance + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_STATUS Status; + EFI_HANDLE FvbHandle; + + ASSERT (FvbInstance != NULL); + if (FvbInstance == NULL) { + return; + } + + CopyMem (&FvbInstance->FvbProtocol, &mFvbProtocolTemplate, sizeof (EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL)); + + FvHeader = &FvbInstance->FvHeader; + if (FvHeader == NULL) { + return; + } + + // + // Set up the devicepath + // + DEBUG ((DEBUG_INFO, "FwBlockService.c: Setting up DevicePath for 0x%lx:\n", FvbInstance->FvBase)); + if (FvHeader->ExtHeaderOffset == 0) { + // + // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH + // + FvbInstance->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate); + if (FvbInstance->DevicePath == NULL) { + DEBUG ((DEBUG_INFO, "SpiFvbServiceSmm.c: Memory allocation for MEMMAP_DEVICE_PATH failed\n")); + return; + } + ((FV_MEMMAP_DEVICE_PATH *) FvbInstance->DevicePath)->MemMapDevPath.StartingAddress = FvbInstance->FvBase; + ((FV_MEMMAP_DEVICE_PATH *) FvbInstance->DevicePath)->MemMapDevPath.EndingAddress = FvbInstance->FvBase + FvHeader->FvLength - 1; + } else { + FvbInstance->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate); + if (FvbInstance->DevicePath == NULL) { + DEBUG ((DEBUG_INFO, "SpiFvbServiceSmm.c: Memory allocation for FV_PIWG_DEVICE_PATH failed\n")); + return; + } + CopyGuid ( + &((FV_PIWG_DEVICE_PATH *)FvbInstance->DevicePath)->FvDevPath.FvName, + (GUID *)(UINTN)(FvbInstance->FvBase + FvHeader->ExtHeaderOffset) + ); + } + + // + // LocateDevicePath fails so install a new interface and device path + // + FvbHandle = NULL; + + Status = gMmst->MmInstallProtocolInterface ( + &FvbHandle, + &gEfiSmmFirmwareVolumeBlockProtocolGuid, + EFI_NATIVE_INTERFACE, + &(FvbInstance->FvbProtocol) + ); + ASSERT_EFI_ERROR (Status); + + Status = gMmst->MmInstallProtocolInterface ( + &FvbHandle, + &gEfiDevicePathProtocolGuid, + EFI_NATIVE_INTERFACE, + &(FvbInstance->DevicePath) + ); + ASSERT_EFI_ERROR (Status); +} + +/** + The function does the necessary initialization work for + Firmware Volume Block Driver. + +**/ +VOID +FvbInitialize ( + VOID + ) +{ + EFI_FVB_INSTANCE *FvbInstance; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_STATUS Status; + UINTN BufferSize; + UINTN Idx; + UINT32 MaxLbaSize; + UINT32 BytesWritten; + UINTN BytesErased; + + mPlatformFvBaseAddress[0].FvBase = PcdGet32(PcdFlashNvStorageVariableBase); + mPlatformFvBaseAddress[0].FvSize = PcdGet32(PcdFlashNvStorageVariableSize); + mPlatformFvBaseAddress[1].FvBase = PcdGet32(PcdFlashMicrocodeFvBase); + mPlatformFvBaseAddress[1].FvSize = PcdGet32(PcdFlashMicrocodeFvSize); + mPlatformDefaultBaseAddress[0].FvBase = PcdGet32(PcdFlashNvStorageVariableBase); + mPlatformDefaultBaseAddress[0].FvSize = PcdGet32(PcdFlashNvStorageVariableSize); + mPlatformDefaultBaseAddress[1].FvBase = PcdGet32(PcdFlashMicrocodeFvBase); + mPlatformDefaultBaseAddress[1].FvSize = PcdGet32(PcdFlashMicrocodeFvSize); + + // + // We will only continue with FVB installation if the + // SPI is the active BIOS state + // + { + // + // Make sure all FVB are valid and/or fix if possible + // + for (Idx = 0;; Idx++) { + if (mPlatformFvBaseAddress[Idx].FvSize == 0 && mPlatformFvBaseAddress[Idx].FvBase == 0) { + break; + } + + BaseAddress = mPlatformFvBaseAddress[Idx].FvBase; + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + + if (!IsFvHeaderValid (BaseAddress, FvHeader)) { + BytesWritten = 0; + BytesErased = 0; + DEBUG ((DEBUG_ERROR, "ERROR - The FV in 0x%x is invalid!\n", FvHeader)); + Status = GetFvbInfo (BaseAddress, &FvHeader); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "ERROR - Can't recovery FV header at 0x%x. GetFvbInfo Status %r\n", BaseAddress, Status)); + continue; + } + DEBUG ((DEBUG_INFO, "Rewriting FV header at 0x%X with static data\n", BaseAddress)); + // + // Spi erase + // + BytesErased = (UINTN) FvHeader->BlockMap->Length; + Status = SpiFlashBlockErase( (UINTN) BaseAddress, &BytesErased); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "ERROR - SpiFlashBlockErase Error %r\n", Status)); + continue; + } + if (BytesErased != FvHeader->BlockMap->Length) { + DEBUG ((DEBUG_WARN, "ERROR - BytesErased != FvHeader->BlockMap->Length\n")); + DEBUG ((DEBUG_INFO, " BytesErased = 0x%X\n Length = 0x%X\n", BytesErased, FvHeader->BlockMap->Length)); + continue; + } + BytesWritten = FvHeader->HeaderLength; + Status = SpiFlashWrite ((UINTN)BaseAddress, &BytesWritten, (UINT8*)FvHeader); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "ERROR - SpiFlashWrite Error %r\n", Status)); + continue; + } + if (BytesWritten != FvHeader->HeaderLength) { + DEBUG ((DEBUG_WARN, "ERROR - BytesWritten != HeaderLength\n")); + DEBUG ((DEBUG_INFO, " BytesWritten = 0x%X\n HeaderLength = 0x%X\n", BytesWritten, FvHeader->HeaderLength)); + continue; + } + Status = SpiFlashLock (); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "ERROR - SpiFlashLock Error %r\n", Status)); + continue; + } + DEBUG ((DEBUG_INFO, "FV Header @ 0x%X restored with static data\n", BaseAddress)); + // + // Clear cache for this range. + // + WriteBackInvalidateDataCacheRange ( (VOID *) (UINTN) BaseAddress, FvHeader->BlockMap->Length); + } + } + + // + // Calculate the total size for all firmware volume block instances + // + BufferSize = 0; + for (Idx = 0; ; Idx++) { + if (mPlatformFvBaseAddress[Idx].FvSize == 0 && mPlatformFvBaseAddress[Idx].FvBase == 0) { + break; + } + BaseAddress = mPlatformFvBaseAddress[Idx].FvBase; + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + + if (!IsFvHeaderValid (BaseAddress, FvHeader)) { + DEBUG ((DEBUG_WARN, "ERROR - The FV in 0x%x is invalid!\n", FvHeader)); + continue; + } + + BufferSize += (FvHeader->HeaderLength + + sizeof (EFI_FVB_INSTANCE) - + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + ); + } + + mFvbModuleGlobal.FvbInstance = (EFI_FVB_INSTANCE *) AllocateRuntimeZeroPool (BufferSize); + if (mFvbModuleGlobal.FvbInstance == NULL) { + ASSERT (FALSE); + return; + } + + MaxLbaSize = 0; + FvbInstance = mFvbModuleGlobal.FvbInstance; + mFvbModuleGlobal.NumFv = 0; + + for (Idx = 0; ; Idx++) { + if (mPlatformFvBaseAddress[Idx].FvSize == 0 && mPlatformFvBaseAddress[Idx].FvBase == 0) { + break; + } + BaseAddress = mPlatformFvBaseAddress[Idx].FvBase; + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + + if (!IsFvHeaderValid (BaseAddress, FvHeader)) { + DEBUG ((DEBUG_WARN, "ERROR - The FV in 0x%x is invalid!\n", FvHeader)); + continue; + } + + FvbInstance->Signature = FVB_INSTANCE_SIGNATURE; + CopyMem (&(FvbInstance->FvHeader), FvHeader, FvHeader->HeaderLength); + + FvHeader = &(FvbInstance->FvHeader); + FvbInstance->FvBase = (UINTN)BaseAddress; + + // + // Process the block map for each FV + // + FvbInstance->NumOfBlocks = 0; + for (PtrBlockMapEntry = FvHeader->BlockMap; + PtrBlockMapEntry->NumBlocks != 0; + PtrBlockMapEntry++) { + // + // Get the maximum size of a block. + // + if (MaxLbaSize < PtrBlockMapEntry->Length) { + MaxLbaSize = PtrBlockMapEntry->Length; + } + FvbInstance->NumOfBlocks += PtrBlockMapEntry->NumBlocks; + } + + // + // Add a FVB Protocol Instance + // + InstallFvbProtocol (FvbInstance); + mFvbModuleGlobal.NumFv++; + + // + // Move on to the next FvbInstance + // + FvbInstance = (EFI_FVB_INSTANCE *) ((UINTN)((UINT8 *)FvbInstance) + + FvHeader->HeaderLength + + (sizeof (EFI_FVB_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))); + + } + } +} diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.h b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.h new file mode 100644 index 0000000000..d3a5eceb26 --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.h @@ -0,0 +1,22 @@ +/** @file + Definitions common to MM implementation in this driver. + + Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SPI_FVB_SERVICE_MM_H_ +#define _SPI_FVB_SERVICE_MM_H_ + +/** + The function does the necessary initialization work for + Firmware Volume Block Driver. + +**/ +VOID +FvbInitialize ( + VOID + ); + +#endif diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf new file mode 100644 index 0000000000..b5c7f1ca81 --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf @@ -0,0 +1,68 @@ +### @file +# Component description file for the Serial Flash device Runtime driver. +# +# Copyright (c) 2017-2019, Intel Corporation. All rights reserved.
+# Copyright (c) Microsoft Corporation.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + +[Defines] + INF_VERSION = 0x00010017 + BASE_NAME = SpiFvbServiceSmm + FILE_GUID = 68A10D85-6858-4402-B070-028B3EA21747 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_SMM_DRIVER + PI_SPECIFICATION_VERSION = 1.10 + ENTRY_POINT = SpiFvbTraditionalMmInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[LibraryClasses] + PcdLib + MemoryAllocationLib + CacheMaintenanceLib + BaseMemoryLib + DebugLib + BaseLib + UefiBootServicesTableLib + UefiDriverEntryPoint + SpiFlashCommonLib + MmServicesTableLib + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelSiliconPkg/IntelSiliconPkg.dec + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES + gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase ## CONSUMES + gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize ## CONSUMES + +[Sources] + FvbInfo.c + SpiFvbServiceCommon.h + SpiFvbServiceCommon.c + SpiFvbServiceMm.h + SpiFvbServiceMm.c + SpiFvbServiceTraditionalMm.c + +[Protocols] + gEfiDevicePathProtocolGuid ## PRODUCES + gEfiSmmFirmwareVolumeBlockProtocolGuid ## PRODUCES + +[Guids] + gEfiFirmwareFileSystem2Guid ## CONSUMES + gEfiSystemNvDataFvGuid ## CONSUMES + +[Depex] + TRUE diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.c new file mode 100644 index 0000000000..979180d5ff --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.c @@ -0,0 +1,32 @@ +/** @file + MM driver source for several Serial Flash devices + which are compliant with the Intel(R) Serial Flash Interface Compatibility Specification. + + Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SpiFvbServiceCommon.h" +#include "SpiFvbServiceMm.h" + +/** + The driver Standalone MM entry point. + + @param[in] ImageHandle Image handle of this driver. + @param[in] MmSystemTable A pointer to the MM system table. + + @retval EFI_SUCCESS This function always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SpiFvbStandaloneMmInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *MmSystemTable + ) +{ + FvbInitialize (); + + return EFI_SUCCESS; +} diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf new file mode 100644 index 0000000000..bb957b614d --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf @@ -0,0 +1,67 @@ +### @file +# Component description file for the Serial Flash device Standalone MM driver. +# +# Copyright (c) 2017-2019, Intel Corporation. All rights reserved.
+# Copyright (c) Microsoft Corporation.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +### + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SpiFvbServiceStandaloneMm + FILE_GUID = E6313655-8BD0-4EAB-B319-AD5E212CE6AB + VERSION_STRING = 1.0 + MODULE_TYPE = MM_STANDALONE + PI_SPECIFICATION_VERSION = 0x00010032 + ENTRY_POINT = SpiFvbStandaloneMmInitialize + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[LibraryClasses] + BaseLib + BaseMemoryLib + CacheMaintenanceLib + DebugLib + MemoryAllocationLib + PcdLib + MmServicesTableLib + SpiFlashCommonLib + StandaloneMmDriverEntryPoint + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelSiliconPkg/IntelSiliconPkg.dec + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES + gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase ## CONSUMES + gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize ## CONSUMES + +[Sources] + FvbInfo.c + SpiFvbServiceCommon.h + SpiFvbServiceCommon.c + SpiFvbServiceMm.h + SpiFvbServiceMm.c + SpiFvbServiceStandaloneMm.c + +[Protocols] + gEfiDevicePathProtocolGuid ## PRODUCES + gEfiSmmFirmwareVolumeBlockProtocolGuid ## PRODUCES + +[Guids] + gEfiFirmwareFileSystem2Guid ## CONSUMES + gEfiSystemNvDataFvGuid ## CONSUMES + +[Depex] + TRUE diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceTraditionalMm.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceTraditionalMm.c new file mode 100644 index 0000000000..85d880f832 --- /dev/null +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceTraditionalMm.c @@ -0,0 +1,32 @@ +/** @file + MM driver source for several Serial Flash devices + which are compliant with the Intel(R) Serial Flash Interface Compatibility Specification. + + Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SpiFvbServiceCommon.h" +#include "SpiFvbServiceMm.h" + +/** + The driver Traditional MM entry point. + + @param[in] ImageHandle Image handle of this driver. + @param[in] SystemTable A pointer to the EFI system table. + + @retval EFI_SUCCESS This function always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SpiFvbTraditionalMmInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + FvbInitialize (); + + return EFI_SUCCESS; +} diff --git a/IntelSiliconPkg/IntelSiliconPkg.dsc b/IntelSiliconPkg/IntelSiliconPkg.dsc index a4cd4b2e22..8af66b2f00 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dsc +++ b/IntelSiliconPkg/IntelSiliconPkg.dsc @@ -40,6 +40,9 @@ PeiGetVtdPmrAlignmentLib|IntelSiliconPkg/Library/PeiGetVtdPmrAlignmentLib/PeiGetVtdPmrAlignmentLib.inf TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf + SpiFlashCommonLib|IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf [LibraryClasses.common.PEIM] PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf @@ -61,8 +64,14 @@ [LibraryClasses.common.DXE_SMM_DRIVER] MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf + MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf +[LibraryClasses.common.MM_STANDALONE] + MemoryAllocationLib|StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf + MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf + StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf + ################################################################################################### # # Components Section - list of the modules and components that will be processed by compilation @@ -86,6 +95,8 @@ IntelSiliconPkg/Library/DxeSmbiosDataHobLib/DxeSmbiosDataHobLib.inf IntelSiliconPkg/Feature/PcieSecurity/IntelPciDeviceSecurityDxe/IntelPciDeviceSecurityDxe.inf IntelSiliconPkg/Feature/PcieSecurity/SamplePlatformDevicePolicyDxe/SamplePlatformDevicePolicyDxe.inf + IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf + IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.inf IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf From 2bf72da557f144708649e0c4b9cb65bdf9c9ebd9 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 15:08:33 -0700 Subject: [PATCH 10/26] IntelSiliconPkg: Add flash region GUIDs REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 This change identifies flash regions by GUID instead of fixed values since the flash region identifiers are now defined in IntelSiliconPkg and different boards may want to associate a flash region identifier with a board/platform specific value. The flash region GUIDs are intended to provide identifier consistency across board implementations improving portability of the code among IntelSiliconPkg consumers. Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Nate DeSimone Signed-off-by: Michael Kubacki Reviewed-by: Sai Chaganty Reviewed-by: Nate DeSimone --- IntelSiliconPkg/Include/Guid/FlashRegion.h | 45 ++++++++++++++++++++++ IntelSiliconPkg/IntelSiliconPkg.dec | 18 +++++++++ 2 files changed, 63 insertions(+) create mode 100644 IntelSiliconPkg/Include/Guid/FlashRegion.h diff --git a/IntelSiliconPkg/Include/Guid/FlashRegion.h b/IntelSiliconPkg/Include/Guid/FlashRegion.h new file mode 100644 index 0000000000..77a3d8c38f --- /dev/null +++ b/IntelSiliconPkg/Include/Guid/FlashRegion.h @@ -0,0 +1,45 @@ +/** @file + + Flash region GUID definitions. + + Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __FLASH_REGION_H__ +#define __FLASH_REGION_H__ + +#define FLASH_REGION_DESCRIPTOR_GUID { 0xaf90c5d8, 0xb8d1, 0x4cc2, {0xbb, 0xc1, 0xc9, 0xeb, 0x51, 0x2d, 0x2f, 0x82 } } +#define FLASH_REGION_BIOS_GUID { 0x6fe65e44, 0x00fc, 0x4ae7, {0xb7, 0x61, 0xb4, 0x8f, 0x17, 0x0f, 0x4d, 0x85 } } +#define FLASH_REGION_ME_GUID { 0xebbfcd3f, 0xe8de, 0x40c1, {0x9c, 0xfd, 0xd3, 0x4e, 0x36, 0xdc, 0x0d, 0xe4 } } +#define FLASH_REGION_GBE_GUID { 0x79d11264, 0xed7a, 0x4556, {0xaf, 0xeb, 0x4b, 0x23, 0x93, 0x9c, 0x88, 0xe7 } } +#define FLASH_REGION_PLATFORM_DATA_GUID { 0x4330a7d5, 0xad54, 0x456a, {0x8f, 0xe1, 0xea, 0x4f, 0xa1, 0xbe, 0x58, 0xd0 } } +#define FLASH_REGION_DER_GUID { 0x83014a66, 0xfd0b, 0x4049, {0xb3, 0xf7, 0x85, 0x6c, 0x26, 0xbb, 0xb4, 0x34 } } +#define FLASH_REGION_SECONDARY_BIOS_GUID { 0x993382b4, 0x5a43, 0x4cb0, {0xba, 0x77, 0x06, 0xb9, 0x16, 0xc5, 0x6a, 0x18 } } +#define FLASH_REGION_MICROCODE_PATCH_GUID { 0x3e97eeeb, 0xc5f7, 0x4af6, {0xa8, 0x61, 0x22, 0xfd, 0x8d, 0x8c, 0xa1, 0x84 } } +#define FLASH_REGION_EC_GUID { 0x55a62589, 0x1b0c, 0x43ad, {0x91, 0xe2, 0x6f, 0xcc, 0x08, 0xc6, 0x9b, 0x75 } } +#define FLASH_REGION_DEVICE_EXPANSION_GUID { 0x0dc8f30b, 0x472b, 0x48cc, {0xbd, 0x22, 0xe2, 0x7c, 0xfe, 0xc2, 0xc3, 0x7e } } +#define FLASH_REGION_IE_GUID { 0xf930a983, 0xb72e, 0x41cc, {0x98, 0x1a, 0x2c, 0x60, 0x6b, 0xf5, 0x7e, 0xdb } } +#define FLASH_REGION_10GBE_A_GUID { 0xde09e662, 0x831f, 0x4ace, {0x9a, 0x06, 0x31, 0x7c, 0xcd, 0x9c, 0x38, 0x3e } } +#define FLASH_REGION_10GBE_B_GUID { 0x7776d88b, 0x48cb, 0x42a4, {0xb5, 0x93, 0x9b, 0x50, 0x9c, 0x8e, 0xd2, 0xae } } +#define FLASH_REGION_ALL_GUID { 0xbabe60dc, 0xf88d, 0x4584, {0x9e, 0x54, 0x57, 0x44, 0x4b, 0xe2, 0x6e, 0xf3 } } +#define FLASH_REGION_MAX_GUID { 0x74c2e3c1, 0x8faa, 0x4659, {0xa7, 0xbb, 0x87, 0x1f, 0xbb, 0x61, 0xd3, 0xb4 } } + +extern EFI_GUID gFlashRegionDescriptorGuid; +extern EFI_GUID gFlashRegionBiosGuid; +extern EFI_GUID gFlashRegionMeGuid; +extern EFI_GUID gFlashRegionGbeGuid; +extern EFI_GUID gFlashRegionPlatformDataGuid; +extern EFI_GUID gFlashRegionDerGuid; +extern EFI_GUID gFlashRegionSecondaryBiosGuid; +extern EFI_GUID gFlashRegionMicrocodePatchGuid; +extern EFI_GUID gFlashRegionEcGuid; +extern EFI_GUID gFlashRegionDeviceExpansion2Guid; +extern EFI_GUID gFlashRegionIeGuid; +extern EFI_GUID gFlashRegion10GbeAGuid; +extern EFI_GUID gFlashRegion10GbeBGuid; +extern EFI_GUID gFlashRegionAllGuid; +extern EFI_GUID gFlashRegionMaxGuid; + +#endif diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index a70f9e1cd8..01e2d9978a 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -4,6 +4,7 @@ # This package provides common open source Intel silicon modules. # # Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -74,6 +75,23 @@ ## Include/Guid/MicrocodeShadowInfoHob.h gEdkiiMicrocodeStorageTypeFlashGuid = { 0x2cba01b3, 0xd391, 0x4598, { 0x8d, 0x89, 0xb7, 0xfc, 0x39, 0x22, 0xfd, 0x71 } } + ## Include/Guid/FlashRegion.h + gFlashRegionDescriptorGuid = { 0xaf90c5d8, 0xb8d1, 0x4cc2, {0xbb, 0xc1, 0xc9, 0xeb, 0x51, 0x2d, 0x2f, 0x82 } } + gFlashRegionBiosGuid = { 0x6fe65e44, 0x00fc, 0x4ae7, {0xb7, 0x61, 0xb4, 0x8f, 0x17, 0x0f, 0x4d, 0x85 } } + gFlashRegionMeGuid = { 0xebbfcd3f, 0xe8de, 0x40c1, {0x9c, 0xfd, 0xd3, 0x4e, 0x36, 0xdc, 0x0d, 0xe4 } } + gFlashRegionGbeGuid = { 0x79d11264, 0xed7a, 0x4556, {0xaf, 0xeb, 0x4b, 0x23, 0x93, 0x9c, 0x88, 0xe7 } } + gFlashRegionPlatformDataGuid = { 0x4330a7d5, 0xad54, 0x456a, {0x8f, 0xe1, 0xea, 0x4f, 0xa1, 0xbe, 0x58, 0xd0 } } + gFlashRegionDerGuid = { 0x83014a66, 0xfd0b, 0x4049, {0xb3, 0xf7, 0x85, 0x6c, 0x26, 0xbb, 0xb4, 0x34 } } + gFlashRegionSecondaryBiosGuid = { 0x993382b4, 0x5a43, 0x4cb0, {0xba, 0x77, 0x06, 0xb9, 0x16, 0xc5, 0x6a, 0x18 } } + gFlashRegionMicrocodePatchGuid = { 0x3e97eeeb, 0xc5f7, 0x4af6, {0xa8, 0x61, 0x22, 0xfd, 0x8d, 0x8c, 0xa1, 0x84 } } + gFlashRegionEcGuid = { 0x55a62589, 0x1b0c, 0x43ad, {0x91, 0xe2, 0x6f, 0xcc, 0x08, 0xc6, 0x9b, 0x75 } } + gFlashRegionDeviceExpansionGuid = { 0x0dc8f30b, 0x472b, 0x48cc, {0xbd, 0x22, 0xe2, 0x7c, 0xfe, 0xc2, 0xc3, 0x7e } } + gFlashRegionIeGuid = { 0xf930a983, 0xb72e, 0x41cc, {0x98, 0x1a, 0x2c, 0x60, 0x6b, 0xf5, 0x7e, 0xdb } } + gFlashRegion10GbeAGuid = { 0xde09e662, 0x831f, 0x4ace, {0x9a, 0x06, 0x31, 0x7c, 0xcd, 0x9c, 0x38, 0x3e } } + gFlashRegion10GbeBGuid = { 0x7776d88b, 0x48cb, 0x42a4, {0xb5, 0x93, 0x9b, 0x50, 0x9c, 0x8e, 0xd2, 0xae } } + gFlashRegionAllGuid = { 0xbabe60dc, 0xf88d, 0x4584, {0x9e, 0x54, 0x57, 0x44, 0x4b, 0xe2, 0x6e, 0xf3 } } + gFlashRegionMaxGuid = { 0x74c2e3c1, 0x8faa, 0x4659, {0xa7, 0xbb, 0x87, 0x1f, 0xbb, 0x61, 0xd3, 0xb4 } } + [Ppis] ## Include/Ppi/Spi.h gPchSpiPpiGuid = { 0x104c7177, 0xc2e6, 0x44f0, { 0xae, 0xe3, 0x9d, 0x0d, 0x9a, 0x52, 0xca, 0xdf } } From faad004e30e18e7611b22793faecb8dba2cb94bf Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Thu, 28 Oct 2021 15:08:34 -0700 Subject: [PATCH 11/26] IntelSiliconPkg: Identify flash regions by GUID REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3307 Adds a new SPI 2 protocol (and corresponding PPI) that identify flash regions by GUID instead of fixed values defined in an enum. Packages consuming IntelSiliconPkg are able to associate a given GUID with their chosen values based on their SPI flash details as implemented in their PCH_SPI2_PROTOCOL instance. Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Nate DeSimone Signed-off-by: Michael Kubacki Reviewed-by: Sai Chaganty Reviewed-by: Nate DeSimone --- IntelSiliconPkg/Include/Ppi/Spi2.h | 31 ++ IntelSiliconPkg/Include/Protocol/Spi2.h | 283 ++++++++++++++++++ IntelSiliconPkg/IntelSiliconPkg.dec | 8 + .../SmmSpiFlashCommonLib.c | 16 +- .../SmmSpiFlashCommonLib.inf | 7 +- .../SmmSpiFlashCommonLib/SpiFlashCommon.c | 32 +- 6 files changed, 352 insertions(+), 25 deletions(-) create mode 100644 IntelSiliconPkg/Include/Ppi/Spi2.h create mode 100644 IntelSiliconPkg/Include/Protocol/Spi2.h diff --git a/IntelSiliconPkg/Include/Ppi/Spi2.h b/IntelSiliconPkg/Include/Ppi/Spi2.h new file mode 100644 index 0000000000..7385c8afe5 --- /dev/null +++ b/IntelSiliconPkg/Include/Ppi/Spi2.h @@ -0,0 +1,31 @@ +/** @file + This file defines the PCH SPI2 PPI which implements the + Intel(R) PCH SPI Host Controller Compatibility Interface. + + This SPI Protocol differs from the PCH SPI 1 Protocol interface + primarily by identifying SPI flash regions by GUID instead + of numeric values. + + Copyright (c) 2019, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _PCH_SPI2_PPI_H_ +#define _PCH_SPI2_PPI_H_ + +#include + +// +// Extern the GUID for PPI users. +// +extern EFI_GUID gPchSpi2PpiGuid; + +/** + Reuse the PCH_SPI2_PROTOCOL definitions + This is possible because the PPI implementation does not rely on a PeiService pointer, + as it uses EDKII Glue Lib to do IO accesses +**/ +typedef PCH_SPI2_PROTOCOL PCH_SPI2_PPI; + +#endif diff --git a/IntelSiliconPkg/Include/Protocol/Spi2.h b/IntelSiliconPkg/Include/Protocol/Spi2.h new file mode 100644 index 0000000000..0877c2ade1 --- /dev/null +++ b/IntelSiliconPkg/Include/Protocol/Spi2.h @@ -0,0 +1,283 @@ +/** @file + This file defines the PCH SPI 2 Protocol which implements the + Intel(R) PCH SPI Host Controller Compatibility Interface. + + This SPI Protocol differs from the PCH SPI 1 Protocol interface + primarily by identifying SPI flash regions by GUID instead + of numeric values. + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _PCH_SPI2_PROTOCOL_H_ +#define _PCH_SPI2_PROTOCOL_H_ + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gPchSpi2ProtocolGuid; +extern EFI_GUID gPchSmmSpi2ProtocolGuid; + +// +// Forward reference for ANSI C compatibility +// +typedef struct _PCH_SPI2_PROTOCOL PCH_SPI2_PROTOCOL; + +// +// Protocol member functions +// + +/** + Read data from the flash part. + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] FlashRegionGuid The Flash Region GUID for flash cycle which corresponds to the type in the descriptor. + @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. + @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received. + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ) ( + IN PCH_SPI2_PROTOCOL *This, + IN EFI_GUID *FlashRegionGuid, + IN UINT32 Address, + IN UINT32 ByteCount, + OUT UINT8 *Buffer + ); + +/** + Write data to the flash part. Remark: Erase may be needed before write to the flash part. + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] FlashRegionGuid The Flash Region GUID for flash cycle which corresponds to the type in the descriptor. + @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. + @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_WRITE) ( + IN PCH_SPI2_PROTOCOL *This, + IN EFI_GUID *FlashRegionGuid, + IN UINT32 Address, + IN UINT32 ByteCount, + IN UINT8 *Buffer + ); + +/** + Erase some area on the flash part. + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] FlashRegionGuid The Flash Region GUID for flash cycle which corresponds to the type in the descriptor. + @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. + @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_ERASE) ( + IN PCH_SPI2_PROTOCOL *This, + IN EFI_GUID *FlashRegionGuid, + IN UINT32 Address, + IN UINT32 ByteCount + ); + +/** + Read SFDP data from the flash part. + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] ComponentNumber The Component Number for chip select + @param[in] Address The starting byte address for SFDP data read. + @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle + @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ_SFDP) ( + IN PCH_SPI2_PROTOCOL *This, + IN UINT8 ComponentNumber, + IN UINT32 Address, + IN UINT32 ByteCount, + OUT UINT8 *SfdpData + ); + +/** + Read Jedec Id from the flash part. + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] ComponentNumber The Component Number for chip select + @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically + @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ_JEDEC_ID) ( + IN PCH_SPI2_PROTOCOL *This, + IN UINT8 ComponentNumber, + IN UINT32 ByteCount, + OUT UINT8 *JedecId + ); + +/** + Write the status register in the flash part. + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically + @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_WRITE_STATUS) ( + IN PCH_SPI2_PROTOCOL *This, + IN UINT32 ByteCount, + IN UINT8 *StatusValue + ); + +/** + Read status register in the flash part. + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically + @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_FLASH_READ_STATUS) ( + IN PCH_SPI2_PROTOCOL *This, + IN UINT32 ByteCount, + OUT UINT8 *StatusValue + ); + +/** + Get the SPI region base and size, based on the enum type + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] FlashRegionGuid The Flash Region GUID for flash cycle which corresponds to the type in the descriptor. + @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base + @param[out] RegionSize The size for the Region 'n' + + @retval EFI_SUCCESS Read success + @retval EFI_INVALID_PARAMETER Invalid region type given + @retval EFI_DEVICE_ERROR The region is not used +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_GET_REGION_ADDRESS) ( + IN PCH_SPI2_PROTOCOL *This, + IN EFI_GUID *FlashRegionGuid, + OUT UINT32 *BaseAddress, + OUT UINT32 *RegionSize + ); + +/** + Read PCH Soft Strap Values + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA. + @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle + @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value. + If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_READ_PCH_SOFTSTRAP) ( + IN PCH_SPI2_PROTOCOL *This, + IN UINT32 SoftStrapAddr, + IN UINT32 ByteCount, + OUT VOID *SoftStrapValue + ); + +/** + Read CPU Soft Strap Values + + @param[in] This Pointer to the PCH_SPI2_PROTOCOL instance. + @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA. + @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle. + @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value. + If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length + It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. + + @retval EFI_SUCCESS Command succeed. + @retval EFI_INVALID_PARAMETER The parameters specified are not valid. + @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. +**/ +typedef +EFI_STATUS +(EFIAPI *PCH_SPI_READ_CPU_SOFTSTRAP) ( + IN PCH_SPI2_PROTOCOL *This, + IN UINT32 SoftStrapAddr, + IN UINT32 ByteCount, + OUT VOID *SoftStrapValue + ); + +/** + These protocols/PPI allows a platform module to perform SPI operations through the + Intel PCH SPI Host Controller Interface. + +**/ +struct _PCH_SPI2_PROTOCOL { + /** + This member specifies the revision of this structure. This field is used to + indicate backwards compatible changes to the protocol. + **/ + UINT8 Revision; + PCH_SPI_FLASH_READ FlashRead; ///< Read data from the flash part. + PCH_SPI_FLASH_WRITE FlashWrite; ///< Write data to the flash part. Remark: Erase may be needed before write to the flash part. + PCH_SPI_FLASH_ERASE FlashErase; ///< Erase some area on the flash part. + PCH_SPI_FLASH_READ_SFDP FlashReadSfdp; ///< Read SFDP data from the flash part. + PCH_SPI_FLASH_READ_JEDEC_ID FlashReadJedecId; ///< Read Jedec Id from the flash part. + PCH_SPI_FLASH_WRITE_STATUS FlashWriteStatus; ///< Write the status register in the flash part. + PCH_SPI_FLASH_READ_STATUS FlashReadStatus; ///< Read status register in the flash part. + PCH_SPI_GET_REGION_ADDRESS GetRegionAddress; ///< Get the SPI region base and size + PCH_SPI_READ_PCH_SOFTSTRAP ReadPchSoftStrap; ///< Read PCH Soft Strap Values + PCH_SPI_READ_CPU_SOFTSTRAP ReadCpuSoftStrap; ///< Read CPU Soft Strap Values +}; + +/** + PCH SPI PPI/PROTOCOL revision number + + Revision 1: Initial version + Revision 2: Identify regions by GUID + +**/ +#define PCH_SPI_SERVICES_REVISION 2 + +#endif diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index 01e2d9978a..964f408652 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -96,15 +96,23 @@ ## Include/Ppi/Spi.h gPchSpiPpiGuid = { 0x104c7177, 0xc2e6, 0x44f0, { 0xae, 0xe3, 0x9d, 0x0d, 0x9a, 0x52, 0xca, 0xdf } } + ## Include/Ppi/Spi2.h + gPchSpi2PpiGuid = { 0x63c40580, 0x10c4, 0x4a8e, { 0xb4, 0x16, 0x86, 0x85, 0x25, 0x7e, 0xce, 0x04 } } + gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } } gEdkiiVTdNullRootEntryTableGuid = { 0x3de0593f, 0x6e3e, 0x4542, { 0xa1, 0xcb, 0xcb, 0xb2, 0xdb, 0xeb, 0xd8, 0xff } } [Protocols] ## Protocols that provide services for the Intel(R) PCH SPI Host Controller Compatibility Interface + # Include/Protocol/Spi.h gPchSpiProtocolGuid = { 0xe007dec0, 0xccc3, 0x4c90, { 0x9c, 0xd0, 0xef, 0x99, 0x38, 0x83, 0x28, 0xcf } } gPchSmmSpiProtocolGuid = { 0x4840e48e, 0xc264, 0x4fef, { 0xb9, 0x34, 0x14, 0x84, 0x0c, 0x95, 0xd8, 0x3f } } + # Include/Protocol/Spi2.h + gPchSpi2ProtocolGuid = { 0x3a99abd1, 0x096c, 0x4399, { 0xb1, 0x68, 0x52, 0xaa, 0x52, 0x64, 0xce, 0x70 } } + gPchSmmSpi2ProtocolGuid = { 0x2d1c0c43, 0x20d3, 0x40ae, { 0x99, 0x07, 0x2d, 0xf0, 0xe7, 0x91, 0x21, 0xa5 } } + gEdkiiPlatformVTdPolicyProtocolGuid = { 0x3d17e448, 0x466, 0x4e20, { 0x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }} ## Protocol for device security policy. diff --git a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c index 689e54ed8e..c636be4e48 100644 --- a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c +++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c @@ -2,21 +2,23 @@ SMM Library instance of SPI Flash Common Library Class Copyright (c) 2021, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include -#include +#include #include -extern PCH_SPI_PROTOCOL *mSpiProtocol; +extern PCH_SPI2_PROTOCOL *mSpi2Protocol; extern UINTN mBiosAreaBaseAddress; extern UINTN mBiosSize; extern UINTN mBiosOffset; /** - The library constructuor. + The library constructor. The function does the necessary initialization work for this library instance. @@ -43,16 +45,16 @@ SmmSpiFlashCommonLibConstructor ( mBiosSize = (UINTN)PcdGet32 (PcdBiosSize); // - // Locate the SMM SPI protocol. + // Locate the SMM SPI2 protocol. // Status = gSmst->SmmLocateProtocol ( - &gPchSmmSpiProtocolGuid, + &gPchSmmSpi2ProtocolGuid, NULL, - (VOID **) &mSpiProtocol + (VOID **) &mSpi2Protocol ); ASSERT_EFI_ERROR (Status); - mSpiProtocol->GetRegionAddress (mSpiProtocol, FlashRegionBios, &BaseAddr, &RegionSize); + mSpi2Protocol->GetRegionAddress (mSpi2Protocol, &gFlashRegionBiosGuid, &BaseAddr, &RegionSize); mBiosOffset = BaseAddr; return Status; } diff --git a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf index 5f36742137..312e38d589 100644 --- a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf +++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf @@ -37,12 +37,15 @@ gIntelSiliconPkgTokenSpaceGuid.PcdBiosAreaBaseAddress ## CONSUMES gIntelSiliconPkgTokenSpaceGuid.PcdBiosSize ## CONSUMES +[Guids] + gFlashRegionBiosGuid + [Sources] SmmSpiFlashCommonLib.c SpiFlashCommon.c [Protocols] - gPchSmmSpiProtocolGuid ## CONSUMES + gPchSmmSpi2ProtocolGuid ## CONSUMES [Depex.X64.DXE_SMM_DRIVER] - gPchSmmSpiProtocolGuid + gPchSmmSpi2ProtocolGuid diff --git a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c index 39f223a1ab..3e97aadbfe 100644 --- a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c +++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c @@ -1,5 +1,5 @@ /** @file - Wrap PCH_SPI_PROTOCOL to provide some library level interfaces + Wrap PCH_SPI2_PROTOCOL to provide some library level interfaces for module use. Copyright (c) 2021, Intel Corporation. All rights reserved.
@@ -8,9 +8,9 @@ #include #include -#include +#include -PCH_SPI_PROTOCOL *mSpiProtocol; +PCH_SPI2_PROTOCOL *mSpi2Protocol; // // Variables for boottime and runtime usage. @@ -125,13 +125,13 @@ SpiFlashWrite ( } else { Length = RemainingBytes; } - Status = mSpiProtocol->FlashWrite ( - mSpiProtocol, - FlashRegionBios, - (UINT32) Offset, - Length, - Buffer - ); + Status = mSpi2Protocol->FlashWrite ( + mSpi2Protocol, + &gFlashRegionBiosGuid, + (UINT32) Offset, + Length, + Buffer + ); if (EFI_ERROR (Status)) { break; } @@ -199,11 +199,11 @@ SpiFlashBlockErase ( RemainingBytes = *NumBytes; - Status = mSpiProtocol->FlashErase ( - mSpiProtocol, - FlashRegionBios, - (UINT32) Offset, - (UINT32) RemainingBytes - ); + Status = mSpi2Protocol->FlashErase ( + mSpi2Protocol, + &gFlashRegionBiosGuid, + (UINT32) Offset, + (UINT32) RemainingBytes + ); return Status; } From eb0e0c0e2ddf4dbc116211cabf65c15a90b0d6a8 Mon Sep 17 00:00:00 2001 From: "Sheng, W" Date: Wed, 3 Nov 2021 14:38:21 +0800 Subject: [PATCH 12/26] IntelSiliconPkg/IntelVTdDxe: Support Multi PCI Root Bus Some system may has multi PCI root bridges. It needs to use PciRootBridgeIo protocol to get the root bridge count. Scan each root bridge to get all PCI devices. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3695 Signed-off-by: Robert Kowalewski Signed-off-by: Sheng Wei Cc: Jenny Huang Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Robert Kowalewski Cc: Albecki Mateusz Cc: Kolakowski Jacek Reviewed-by: Jenny Huang Reviewed-by: Ray Ni --- .../Feature/VTd/IntelVTdDxe/DmaProtection.h | 17 +++++ .../Feature/VTd/IntelVTdDxe/DmarAcpiTable.c | 2 +- .../Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf | 1 + .../Feature/VTd/IntelVTdDxe/PciInfo.c | 70 +++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h index b87978e03d..2d4a1b1b7c 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmaProtection.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -341,6 +342,22 @@ ScanPciBus ( IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback ); +/** + Scan PCI bus and invoke callback function for each PCI devices under all root bus. + + @param[in] Context The context of the callback function. + @param[in] Segment The segment of the source. + @param[in] Callback The callback function in PCI scan. + + @retval EFI_SUCCESS The PCI devices under the bus are scaned. +**/ +EFI_STATUS +ScanAllPciBus ( + IN VOID *Context, + IN UINT16 Segment, + IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback + ); + /** Dump the PCI device information managed by this VTd engine. diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c index b25d55ccc5..7ec6a8e8b2 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c @@ -692,7 +692,7 @@ ProcessDhrd ( mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE; DEBUG ((DEBUG_INFO," ProcessDhrd: with INCLUDE ALL\n")); - Status = ScanPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, 0, ScanBusCallbackRegisterPciDevice); + Status = ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, ScanBusCallbackRegisterPciDevice); if (EFI_ERROR (Status)) { return Status; } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf index 643e224ca5..ab4bb9113f 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf @@ -70,6 +70,7 @@ gEfiPciIoProtocolGuid ## CONSUMES gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES gEdkiiPlatformVTdPolicyProtocolGuid ## SOMETIMES_CONSUMES + gEfiPciRootBridgeIoProtocolGuid ## CONSUMES [Pcd] gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/PciInfo.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/PciInfo.c index 199423a884..c29f9f9360 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/PciInfo.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/PciInfo.c @@ -279,6 +279,76 @@ ScanPciBus ( return EFI_SUCCESS; } +/** + Scan PCI bus and invoke callback function for each PCI devices under all root bus. + + @param[in] Context The context of the callback function. + @param[in] Segment The segment of the source. + @param[in] Callback The callback function in PCI scan. + + @retval EFI_SUCCESS The PCI devices under the bus are scaned. +**/ +EFI_STATUS +ScanAllPciBus ( + IN VOID *Context, + IN UINT16 Segment, + IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + DEBUG ((DEBUG_INFO, "ScanAllPciBus ()\n")); + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciRootBridgeIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((DEBUG_INFO,"Find %d root bridges\n", HandleCount)); + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo + ); + ASSERT_EFI_ERROR (Status); + + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); + ASSERT_EFI_ERROR (Status); + + while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) { + if (Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) { + break; + } + Descriptors++; + } + + if (Descriptors->Desc == ACPI_END_TAG_DESCRIPTOR) { + continue; + } + + DEBUG ((DEBUG_INFO,"Scan root bridges : %d, Segment : %d, Bus : 0x%02X\n", Index, PciRootBridgeIo->SegmentNumber, Descriptors->AddrRangeMin)); + Status = ScanPciBus(Context, (UINT16) PciRootBridgeIo->SegmentNumber, (UINT8) Descriptors->AddrRangeMin, Callback); + if (EFI_ERROR (Status)) { + break; + } + } + + FreePool(HandleBuffer); + + return Status; +} + /** Dump the PCI device information managed by this VTd engine. From 1a4539a656ea282b5a81abc76b6947ad2cb04ce5 Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Wed, 3 Nov 2021 07:44:54 -0700 Subject: [PATCH 13/26] IntelSiliconPkg: Remove SPI v1 PPI and Protocol definitions REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3717 V2 of the PCH SPI PPI and PCH SPI Protocol were recently added to IntelSiliconPkg. This change removes the v1 definitions. V2 is intended to better support multiple silicon generations which aligns with the goals of IntelSiliconPkg. Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Nate DeSimone Cc: Isaac Oram Signed-off-by: Michael Kubacki Reviewed-by: Nate DeSimone Reviewed-by: Sai Chaganty --- IntelSiliconPkg/Include/Ppi/Spi.h | 25 -- IntelSiliconPkg/Include/Protocol/Spi.h | 301 ------------------------- IntelSiliconPkg/IntelSiliconPkg.dec | 7 - 3 files changed, 333 deletions(-) delete mode 100644 IntelSiliconPkg/Include/Ppi/Spi.h delete mode 100644 IntelSiliconPkg/Include/Protocol/Spi.h diff --git a/IntelSiliconPkg/Include/Ppi/Spi.h b/IntelSiliconPkg/Include/Ppi/Spi.h deleted file mode 100644 index e1e6530f59..0000000000 --- a/IntelSiliconPkg/Include/Ppi/Spi.h +++ /dev/null @@ -1,25 +0,0 @@ -/** @file - This file defines the PCH SPI PPI which implements the - Intel(R) PCH SPI Host Controller Compatibility Interface. - - Copyright (c) 2019, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent -**/ -#ifndef _PCH_SPI_PPI_H_ -#define _PCH_SPI_PPI_H_ - -#include - -// -// Extern the GUID for PPI users. -// -extern EFI_GUID gPchSpiPpiGuid; - -/** - Reuse the PCH_SPI_PROTOCOL definitions - This is possible becaues the PPI implementation does not rely on a PeiService pointer, - as it uses EDKII Glue Lib to do IO accesses -**/ -typedef PCH_SPI_PROTOCOL PCH_SPI_PPI; - -#endif diff --git a/IntelSiliconPkg/Include/Protocol/Spi.h b/IntelSiliconPkg/Include/Protocol/Spi.h deleted file mode 100644 index f3e4607a29..0000000000 --- a/IntelSiliconPkg/Include/Protocol/Spi.h +++ /dev/null @@ -1,301 +0,0 @@ -/** @file - This file defines the PCH SPI Protocol which implements the - Intel(R) PCH SPI Host Controller Compatibility Interface. - - Copyright (c) 2021, Intel Corporation. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent -**/ -#ifndef _PCH_SPI_PROTOCOL_H_ -#define _PCH_SPI_PROTOCOL_H_ - -// -// Extern the GUID for protocol users. -// -extern EFI_GUID gPchSpiProtocolGuid; -extern EFI_GUID gPchSmmSpiProtocolGuid; - -// -// Forward reference for ANSI C compatibility -// -typedef struct _PCH_SPI_PROTOCOL PCH_SPI_PROTOCOL; - -// -// SPI protocol data structures and definitions -// - -/** - Flash Region Type -**/ -typedef enum { - FlashRegionDescriptor, - FlashRegionBios, - FlashRegionMe, - FlashRegionGbE, - FlashRegionPlatformData, - FlashRegionDer, - FlashRegionSecondaryBios, - FlashRegionuCodePatch, - FlashRegionEC, - FlashRegionDeviceExpansion2, - FlashRegionIE, - FlashRegion10Gbe_A, - FlashRegion10Gbe_B, - FlashRegion13, - FlashRegion14, - FlashRegion15, - FlashRegionAll, - FlashRegionMax -} FLASH_REGION_TYPE; -// -// Protocol member functions -// - -/** - Read data from the flash part. - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor. - @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. - @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. - @param[out] Buffer The Pointer to caller-allocated buffer containing the dada received. - It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_FLASH_READ) ( - IN PCH_SPI_PROTOCOL *This, - IN FLASH_REGION_TYPE FlashRegionType, - IN UINT32 Address, - IN UINT32 ByteCount, - OUT UINT8 *Buffer - ); - -/** - Write data to the flash part. Remark: Erase may be needed before write to the flash part. - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor. - @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. - @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. - @param[in] Buffer Pointer to caller-allocated buffer containing the data sent during the SPI cycle. - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_FLASH_WRITE) ( - IN PCH_SPI_PROTOCOL *This, - IN FLASH_REGION_TYPE FlashRegionType, - IN UINT32 Address, - IN UINT32 ByteCount, - IN UINT8 *Buffer - ); - -/** - Erase some area on the flash part. - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] FlashRegionType The Flash Region type for flash cycle which is listed in the Descriptor. - @param[in] Address The Flash Linear Address must fall within a region for which BIOS has access permissions. - @param[in] ByteCount Number of bytes in the data portion of the SPI cycle. - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_FLASH_ERASE) ( - IN PCH_SPI_PROTOCOL *This, - IN FLASH_REGION_TYPE FlashRegionType, - IN UINT32 Address, - IN UINT32 ByteCount - ); - -/** - Read SFDP data from the flash part. - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] ComponentNumber The Componen Number for chip select - @param[in] Address The starting byte address for SFDP data read. - @param[in] ByteCount Number of bytes in SFDP data portion of the SPI cycle - @param[out] SfdpData The Pointer to caller-allocated buffer containing the SFDP data received - It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_FLASH_READ_SFDP) ( - IN PCH_SPI_PROTOCOL *This, - IN UINT8 ComponentNumber, - IN UINT32 Address, - IN UINT32 ByteCount, - OUT UINT8 *SfdpData - ); - -/** - Read Jedec Id from the flash part. - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] ComponentNumber The Componen Number for chip select - @param[in] ByteCount Number of bytes in JedecId data portion of the SPI cycle, the data size is 3 typically - @param[out] JedecId The Pointer to caller-allocated buffer containing JEDEC ID received - It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_FLASH_READ_JEDEC_ID) ( - IN PCH_SPI_PROTOCOL *This, - IN UINT8 ComponentNumber, - IN UINT32 ByteCount, - OUT UINT8 *JedecId - ); - -/** - Write the status register in the flash part. - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically - @param[in] StatusValue The Pointer to caller-allocated buffer containing the value of Status register writing - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_FLASH_WRITE_STATUS) ( - IN PCH_SPI_PROTOCOL *This, - IN UINT32 ByteCount, - IN UINT8 *StatusValue - ); - -/** - Read status register in the flash part. - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] ByteCount Number of bytes in Status data portion of the SPI cycle, the data size is 1 typically - @param[out] StatusValue The Pointer to caller-allocated buffer containing the value of Status register received. - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_FLASH_READ_STATUS) ( - IN PCH_SPI_PROTOCOL *This, - IN UINT32 ByteCount, - OUT UINT8 *StatusValue - ); - -/** - Get the SPI region base and size, based on the enum type - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] FlashRegionType The Flash Region type for for the base address which is listed in the Descriptor. - @param[out] BaseAddress The Flash Linear Address for the Region 'n' Base - @param[out] RegionSize The size for the Region 'n' - - @retval EFI_SUCCESS Read success - @retval EFI_INVALID_PARAMETER Invalid region type given - @retval EFI_DEVICE_ERROR The region is not used -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_GET_REGION_ADDRESS) ( - IN PCH_SPI_PROTOCOL *This, - IN FLASH_REGION_TYPE FlashRegionType, - OUT UINT32 *BaseAddress, - OUT UINT32 *RegionSize - ); - -/** - Read PCH Soft Strap Values - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] SoftStrapAddr PCH Soft Strap address offset from FPSBA. - @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle - @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing PCH Soft Strap Value. - If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length - It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_READ_PCH_SOFTSTRAP) ( - IN PCH_SPI_PROTOCOL *This, - IN UINT32 SoftStrapAddr, - IN UINT32 ByteCount, - OUT VOID *SoftStrapValue - ); - -/** - Read CPU Soft Strap Values - - @param[in] This Pointer to the PCH_SPI_PROTOCOL instance. - @param[in] SoftStrapAddr CPU Soft Strap address offset from FCPUSBA. - @param[in] ByteCount Number of bytes in SoftStrap data portion of the SPI cycle. - @param[out] SoftStrapValue The Pointer to caller-allocated buffer containing CPU Soft Strap Value. - If the value of ByteCount is 0, the data type of SoftStrapValue should be UINT16 and SoftStrapValue will be PCH Soft Strap Length - It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read. - - @retval EFI_SUCCESS Command succeed. - @retval EFI_INVALID_PARAMETER The parameters specified are not valid. - @retval EFI_DEVICE_ERROR Device error, command aborts abnormally. -**/ -typedef -EFI_STATUS -(EFIAPI *PCH_SPI_READ_CPU_SOFTSTRAP) ( - IN PCH_SPI_PROTOCOL *This, - IN UINT32 SoftStrapAddr, - IN UINT32 ByteCount, - OUT VOID *SoftStrapValue - ); - -/** - These protocols/PPI allows a platform module to perform SPI operations through the - Intel PCH SPI Host Controller Interface. -**/ -struct _PCH_SPI_PROTOCOL { - /** - This member specifies the revision of this structure. This field is used to - indicate backwards compatible changes to the protocol. - **/ - UINT8 Revision; - PCH_SPI_FLASH_READ FlashRead; ///< Read data from the flash part. - PCH_SPI_FLASH_WRITE FlashWrite; ///< Write data to the flash part. Remark: Erase may be needed before write to the flash part. - PCH_SPI_FLASH_ERASE FlashErase; ///< Erase some area on the flash part. - PCH_SPI_FLASH_READ_SFDP FlashReadSfdp; ///< Read SFDP data from the flash part. - PCH_SPI_FLASH_READ_JEDEC_ID FlashReadJedecId; ///< Read Jedec Id from the flash part. - PCH_SPI_FLASH_WRITE_STATUS FlashWriteStatus; ///< Write the status register in the flash part. - PCH_SPI_FLASH_READ_STATUS FlashReadStatus; ///< Read status register in the flash part. - PCH_SPI_GET_REGION_ADDRESS GetRegionAddress; ///< Get the SPI region base and size - PCH_SPI_READ_PCH_SOFTSTRAP ReadPchSoftStrap; ///< Read PCH Soft Strap Values - PCH_SPI_READ_CPU_SOFTSTRAP ReadCpuSoftStrap; ///< Read CPU Soft Strap Values -}; - -/** - PCH SPI PPI/PROTOCOL revision number - - Revision 1: Initial version -**/ -#define PCH_SPI_SERVICES_REVISION 1 - -#endif diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index 964f408652..e482410bee 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -93,9 +93,6 @@ gFlashRegionMaxGuid = { 0x74c2e3c1, 0x8faa, 0x4659, {0xa7, 0xbb, 0x87, 0x1f, 0xbb, 0x61, 0xd3, 0xb4 } } [Ppis] - ## Include/Ppi/Spi.h - gPchSpiPpiGuid = { 0x104c7177, 0xc2e6, 0x44f0, { 0xae, 0xe3, 0x9d, 0x0d, 0x9a, 0x52, 0xca, 0xdf } } - ## Include/Ppi/Spi2.h gPchSpi2PpiGuid = { 0x63c40580, 0x10c4, 0x4a8e, { 0xb4, 0x16, 0x86, 0x85, 0x25, 0x7e, 0xce, 0x04 } } @@ -105,10 +102,6 @@ [Protocols] ## Protocols that provide services for the Intel(R) PCH SPI Host Controller Compatibility Interface - # Include/Protocol/Spi.h - gPchSpiProtocolGuid = { 0xe007dec0, 0xccc3, 0x4c90, { 0x9c, 0xd0, 0xef, 0x99, 0x38, 0x83, 0x28, 0xcf } } - gPchSmmSpiProtocolGuid = { 0x4840e48e, 0xc264, 0x4fef, { 0xb9, 0x34, 0x14, 0x84, 0x0c, 0x95, 0xd8, 0x3f } } - # Include/Protocol/Spi2.h gPchSpi2ProtocolGuid = { 0x3a99abd1, 0x096c, 0x4399, { 0xb1, 0x68, 0x52, 0xaa, 0x52, 0x64, 0xce, 0x70 } } gPchSmmSpi2ProtocolGuid = { 0x2d1c0c43, 0x20d3, 0x40ae, { 0x99, 0x07, 0x2d, 0xf0, 0xe7, 0x91, 0x21, 0xa5 } } From 05d9504f6242763e261805d40051217f75b0fd0a Mon Sep 17 00:00:00 2001 From: "Sheng, W" Date: Tue, 11 Jan 2022 09:26:33 +0800 Subject: [PATCH 14/26] IntelSiliconPkg/IntelVTdDxe: Reduce Debug Level Reduce the debug level from DEBUG_INFO to DEBUG_VERBOSE in function SubmitQueuedInvalidationDescriptor (). REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3801 Reviewed-by: Ray Ni Reviewed-by: Rangasai V Chaganty Reviewed-by: Jenny Huang Reviewed-by: Robert Kowalewski Signed-off-by: Sheng Wei --- IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c index 7704e4f360..f27ab41851 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c @@ -238,7 +238,7 @@ SubmitQueuedInvalidationDescriptor ( QiDescLength = mVtdUnitInformation[VtdIndex].QiDescLength; BaseDesc = mVtdUnitInformation[VtdIndex].QiDesc; - DEBUG((DEBUG_INFO, "[%d] Submit QI Descriptor [0x%08x, 0x%08x] Free Head (%d)\n", VtdIndex, Desc->Low, Desc->High, mVtdUnitInformation[VtdIndex].QiFreeHead)); + DEBUG((DEBUG_VERBOSE, "[%d] Submit QI Descriptor [0x%08x, 0x%08x] Free Head (%d)\n", VtdIndex, Desc->Low, Desc->High, mVtdUnitInformation[VtdIndex].QiFreeHead)); BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].Low = Desc->Low; BaseDesc[mVtdUnitInformation[VtdIndex].QiFreeHead].High = Desc->High; From 38196587f4f43e50e02d92d151bb736f326caef4 Mon Sep 17 00:00:00 2001 From: "Sheng, W" Date: Mon, 24 Jan 2022 10:43:45 +0800 Subject: [PATCH 15/26] IntelSiliconPkg/VTd: Fix typos It is DRHD(DMA Remapping Hardware Unit Definition). REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3622 Reviewed-by: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Cc: Robert Kowalewski Reviewed-by: Jenny Huang Reviewed-by: Robert Kowalewski Signed-off-by: Sheng Wei --- .../Feature/VTd/IntelVTdDmarPei/DmarTable.c | 12 ++++++------ .../Feature/VTd/IntelVTdDxe/DmarAcpiTable.c | 12 ++++++------ .../Feature/VTd/IntelVTdPmrPei/DmarTable.c | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c index 67e5f06fe1..7a08546f0d 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c @@ -539,14 +539,14 @@ RegisterPciDevice ( } /** - Process DMAR DHRD table. + Process DMAR DRHD table. @param[in] VTdUnitInfo The VTd engine unit information. @param[in] DmarDrhd The DRHD table. **/ VOID -ProcessDhrd ( +ProcessDrhd ( IN VTD_UNIT_INFO *VTdUnitInfo, IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd ) @@ -581,10 +581,10 @@ ProcessDhrd ( if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) { VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = TRUE; - DEBUG ((DEBUG_INFO," ProcessDhrd: with INCLUDE ALL\n")); + DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n")); } else { VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE; - DEBUG ((DEBUG_INFO," ProcessDhrd: without INCLUDE ALL\n")); + DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n")); } VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0; @@ -600,7 +600,7 @@ ProcessDhrd ( return; } - DEBUG ((DEBUG_INFO," ProcessDhrd: ")); + DEBUG ((DEBUG_INFO," ProcessDrhd: ")); switch (DmarDevScopeEntry->Type) { case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT: DEBUG ((DEBUG_INFO,"PCI Endpoint")); @@ -708,7 +708,7 @@ ParseDmarAcpiTableDrhd ( switch (DmarHeader->Type) { case EFI_ACPI_DMAR_TYPE_DRHD: ASSERT (VtdIndex < VtdUnitNumber); - ProcessDhrd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader); + ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader); VtdIndex++; break; diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c index 7ec6a8e8b2..f8fdb2a781 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c @@ -662,7 +662,7 @@ GetPciBusDeviceFunction ( } /** - Process DMAR DHRD table. + Process DMAR DRHD table. @param[in] VtdIndex The index of VTd engine. @param[in] DmarDrhd The DRHD table. @@ -670,7 +670,7 @@ GetPciBusDeviceFunction ( @retval EFI_SUCCESS The DRHD table is processed. **/ EFI_STATUS -ProcessDhrd ( +ProcessDrhd ( IN UINTN VtdIndex, IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd ) @@ -690,7 +690,7 @@ ProcessDhrd ( if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) { mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE; - DEBUG ((DEBUG_INFO," ProcessDhrd: with INCLUDE ALL\n")); + DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n")); Status = ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, ScanBusCallbackRegisterPciDevice); if (EFI_ERROR (Status)) { @@ -698,7 +698,7 @@ ProcessDhrd ( } } else { mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE; - DEBUG ((DEBUG_INFO," ProcessDhrd: without INCLUDE ALL\n")); + DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n")); } DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1)); @@ -709,7 +709,7 @@ ProcessDhrd ( return Status; } - DEBUG ((DEBUG_INFO," ProcessDhrd: ")); + DEBUG ((DEBUG_INFO," ProcessDrhd: ")); switch (DmarDevScopeEntry->Type) { case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT: DEBUG ((DEBUG_INFO,"PCI Endpoint")); @@ -877,7 +877,7 @@ ParseDmarAcpiTableDrhd ( switch (DmarHeader->Type) { case EFI_ACPI_DMAR_TYPE_DRHD: ASSERT (VtdIndex < mVtdUnitNumber); - Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader); + Status = ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader); if (EFI_ERROR (Status)) { return Status; } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c index c87b3f1974..c634362bb3 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c @@ -356,14 +356,14 @@ GetVtdEngineNumber ( } /** - Process DMAR DHRD table. + Process DMAR DRHD table. @param[in] VTdInfo The VTd engine context information. @param[in] VtdIndex The index of VTd engine. @param[in] DmarDrhd The DRHD table. **/ VOID -ProcessDhrd ( +ProcessDrhd ( IN VTD_INFO *VTdInfo, IN UINTN VtdIndex, IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd @@ -415,7 +415,7 @@ ParseDmarAcpiTableDrhd ( switch (DmarHeader->Type) { case EFI_ACPI_DMAR_TYPE_DRHD: ASSERT (VtdIndex < VtdUnitNumber); - ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader); + ProcessDrhd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader); VtdIndex++; break; From a7e0aac9d398ca94092630f64ecf7d1403f0dcae Mon Sep 17 00:00:00 2001 From: "Sheng, W" Date: Mon, 24 Jan 2022 10:43:46 +0800 Subject: [PATCH 16/26] IntelSiliconPkg/VTd: Update VTd register structs Update VTd register structs accroding to VTd spec ver 3.3 REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3765 Reviewed-by: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Cc: Robert Kowalewski Reviewed-by: Jenny Huang Signed-off-by: Sheng Wei --- .../VTd/IntelVTdDmarPei/IntelVTdDmar.c | 3 +- .../VTd/IntelVTdDmarPei/TranslationTable.c | 23 ++++++++++--- .../VTd/IntelVTdDxe/TranslationTable.c | 22 ++++++++++-- .../Feature/VTd/IntelVTdDxe/VtdReg.c | 7 ++-- .../Include/IndustryStandard/Vtd.h | 34 ++++++++++++++----- 5 files changed, 68 insertions(+), 21 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c index 40ba88c66b..507e8f2641 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c @@ -631,10 +631,8 @@ DumpVtdECapRegs ( DEBUG ((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC)); DEBUG ((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO)); DEBUG ((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV)); - DEBUG ((DEBUG_INFO, " ECS - 0x%x\n", ECapReg->Bits.ECS)); DEBUG ((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS)); DEBUG ((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST)); - DEBUG ((DEBUG_INFO, " DIS - 0x%x\n", ECapReg->Bits.DIS)); DEBUG ((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID)); DEBUG ((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS)); DEBUG ((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS)); @@ -642,6 +640,7 @@ DumpVtdECapRegs ( DEBUG ((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS)); DEBUG ((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS)); DEBUG ((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS)); + DEBUG ((DEBUG_INFO, " ADMS - 0x%x\n", ECapReg->Bits.ADMS)); } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c index 9391e298f3..bd54986701 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c @@ -884,13 +884,26 @@ SetupTranslationTable ( return Status; } - if (VtdUnitInfo->ECapReg.Bits.ECS) { - DEBUG ((DEBUG_INFO, "CreateExtContextEntry - %d\n", Index)); - Status = CreateExtContextEntry (VtdUnitInfo); + if (VtdUnitInfo->ECapReg.Bits.SMTS) { + if (VtdUnitInfo->ECapReg.Bits.DEP_24) { + DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n")); + ASSERT(FALSE); + Status = EFI_UNSUPPORTED; + } else { + Status = CreateExtContextEntry (VtdUnitInfo); + } } else { - DEBUG ((DEBUG_INFO, "CreateContextEntry - %d\n", Index)); - Status = CreateContextEntry (VtdUnitInfo); + if (VtdUnitInfo->ECapReg.Bits.DEP_24) { + // + // To compatible with pervious VTd engine + // It was ECS(Extended Context Support) bit. + // + Status = CreateExtContextEntry (VtdUnitInfo); + } else { + Status = CreateContextEntry (VtdUnitInfo); + } } + if (EFI_ERROR (Status)) { return Status; } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c index 61d5b3f91f..67428ec545 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c @@ -382,11 +382,27 @@ SetupTranslationTable ( for (Index = 0; Index < mVtdUnitNumber; Index++) { DEBUG((DEBUG_INFO, "CreateContextEntry - %d\n", Index)); - if (mVtdUnitInformation[Index].ECapReg.Bits.ECS) { - Status = CreateExtContextEntry (Index); + + if (mVtdUnitInformation[Index].ECapReg.Bits.SMTS) { + if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) { + DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n")); + ASSERT(FALSE); + Status = EFI_UNSUPPORTED; + } else { + Status = CreateExtContextEntry (Index); + } } else { - Status = CreateContextEntry (Index); + if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) { + // + // To compatible with pervious VTd engine + // It was ECS(Extended Context Support) bit. + // + Status = CreateExtContextEntry (Index); + } else { + Status = CreateContextEntry (Index); + } } + if (EFI_ERROR (Status)) { return Status; } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c index f27ab41851..0e405cf19b 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c @@ -698,10 +698,8 @@ DumpVtdECapRegs ( DEBUG((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC)); DEBUG((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO)); DEBUG((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV)); - DEBUG((DEBUG_INFO, " ECS - 0x%x\n", ECapReg->Bits.ECS)); DEBUG((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS)); DEBUG((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST)); - DEBUG((DEBUG_INFO, " DIS - 0x%x\n", ECapReg->Bits.DIS)); DEBUG((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID)); DEBUG((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS)); DEBUG((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS)); @@ -709,6 +707,8 @@ DumpVtdECapRegs ( DEBUG((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS)); DEBUG((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS)); DEBUG((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS)); + DEBUG((DEBUG_INFO, " SMTS - 0x%x\n", ECapReg->Bits.SMTS)); + DEBUG((DEBUG_INFO, " ADMS - 0x%x\n", ECapReg->Bits.ADMS)); } /** @@ -769,9 +769,10 @@ DumpVtdRegs ( DEBUG((DEBUG_INFO, " FRCD_REG[%d] - 0x%016lx %016lx\n", Index, FrcdReg.Uint64[1], FrcdReg.Uint64[0])); if (FrcdReg.Uint64[1] != 0 || FrcdReg.Uint64[0] != 0) { DEBUG((DEBUG_INFO, " Fault Info - 0x%016lx\n", VTD_64BITS_ADDRESS(FrcdReg.Bits.FILo, FrcdReg.Bits.FIHi))); + DEBUG((DEBUG_INFO, " Fault Bit - %d\n", FrcdReg.Bits.F)); SourceId.Uint16 = (UINT16)FrcdReg.Bits.SID; DEBUG((DEBUG_INFO, " Source - B%02x D%02x F%02x\n", SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - DEBUG((DEBUG_INFO, " Type - %x (%a)\n", FrcdReg.Bits.T, FrcdReg.Bits.T ? "read" : "write")); + DEBUG((DEBUG_INFO, " Type - 0x%02x\n", (FrcdReg.Bits.T1 << 1) | FrcdReg.Bits.T2)); DEBUG((DEBUG_INFO, " Reason - %x (Refer to VTd Spec, Appendix A)\n", FrcdReg.Bits.FR)); } } diff --git a/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b/IntelSiliconPkg/Include/IndustryStandard/Vtd.h index 208463fc8c..27a0450d5c 100644 --- a/IntelSiliconPkg/Include/IndustryStandard/Vtd.h +++ b/IntelSiliconPkg/Include/IndustryStandard/Vtd.h @@ -216,6 +216,7 @@ typedef union { #define B_GSTS_REG_RTPS BIT30 #define B_GSTS_REG_TE BIT31 #define R_RTADDR_REG 0x20 +#define V_RTADDR_REG_TTM_ADM (BIT11|BIT10) #define R_CCMD_REG 0x28 #define B_CCMD_REG_CIRG_MASK (BIT62|BIT61) #define V_CCMD_REG_CIRG_GLOBAL BIT61 @@ -334,7 +335,10 @@ typedef union { UINT8 FL1GP:1; // First Level 1-GByte Page Support UINT8 Rsvd_57:2; UINT8 PI:1; // Posted Interrupts Support - UINT8 Rsvd_60:4; + UINT8 FL5LP:1; // First Level 5-level Paging Support + UINT8 Rsvd_61:1; + UINT8 ESIRTPS:1; // Enhanced Set Interrupt Remap Table Pointer Support + UINT8 ESRTPS:1; // Enhanced Set Root Table Pointer Support } Bits; UINT64 Uint64; } VTD_CAP_REG; @@ -346,7 +350,7 @@ typedef union { UINT8 DT:1; // Device-TLB support UINT8 IR:1; // Interrupt Remapping support UINT8 EIM:1; // Extended Interrupt Mode - UINT8 Rsvd_5:1; + UINT8 DEP_5:1; UINT8 PT:1; // Pass Through UINT8 SC:1; // Snoop Control @@ -354,11 +358,11 @@ typedef union { UINT16 Rsvd_18:2; UINT16 MHMV:4; // Maximum Handle Mask Value - UINT8 ECS:1; // Extended Context Support + UINT8 DEP_24:1; UINT8 MTS:1; // Memory Type Support UINT8 NEST:1; // Nested Translation Support - UINT8 DIS:1; // Deferred Invalidate Support - UINT8 PASID:1; // Process Address Space ID Support + UINT8 Rsvd_27:1; + UINT8 DEP_28:1; UINT8 PRS:1; // Page Request Support UINT8 ERS:1; // Execute Request Support UINT8 SRS:1; // Supervisor Request Support @@ -367,7 +371,20 @@ typedef union { UINT32 NWFS:1; // No Write Flag Support UINT32 EAFS:1; // Extended Accessed Flag Support UINT32 PSS:5; // PASID Size Supported - UINT32 Rsvd_40:24; + UINT32 PASID:1; // Process Address Space ID Support + UINT32 DIT:1; // Device-TLB Invalidation Throttle + UINT32 PDS:1; // Page-request Drain Support + UINT32 SMTS:1; // Scalable Mode Translation Support + UINT32 VCS:1; // Virtual Command Support + UINT32 SLADS:1; // Second-Level Accessed Dirty Support + UINT32 SLTS:1; // Second-level Translation Support + UINT32 FLTS:1; // First-level Translation Support + UINT32 SMPWCS:1; // Scalable-Mode Page-walk Coherency Support + UINT32 RPS:1; // RID-PASID Support + UINT32 Rsvd_50:2; + UINT32 ADMS:1; // Abort DMA Mode Support + UINT32 RPRIVS:1; // RID_PRIV Support + UINT32 Rsvd_54:10; } Bits; UINT64 Uint64; } VTD_ECAP_REG; @@ -379,7 +396,8 @@ typedef union { UINT32 FIHi:32; // FaultInfo UINT32 SID:16; // Source Identifier - UINT32 Rsvd_80:13; + UINT32 Rsvd_80:12; + UINT32 T2:1; // Type bit2 (0: Write/Read, 1: Page/AtomicOp) UINT32 PRIV:1; // Privilege Mode Requested UINT32 EXE:1; // Execute Permission Requested UINT32 PP:1; // PASID Present @@ -387,7 +405,7 @@ typedef union { UINT32 FR:8; // Fault Reason UINT32 PV:20; // PASID Value UINT32 AT:2; // Address Type - UINT32 T:1; // Type (0: Write, 1: Read) + UINT32 T1:1; // Type bit1 (0: Write/Page, 1: Read/AtomicOp) UINT32 F:1; // Fault } Bits; UINT64 Uint64[2]; From bc698bd2f2790a94b53e2c4712cc26ee1bce861b Mon Sep 17 00:00:00 2001 From: "Sheng, W" Date: Mon, 24 Jan 2022 10:43:47 +0800 Subject: [PATCH 17/26] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode If VTd ECAP_REG.ADMS bit is set, abort DMA mode is supported. When VTd Abort DMA Mode is enabled, hardware will abort all DMA operations without the need to set up a root-table with each entry marked as not-present. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3766 Reviewed-by: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Cc: Robert Kowalewski Reviewed-by: Jenny Huang Signed-off-by: Sheng Wei --- .../VTd/IntelVTdDmarPei/IntelVTdDmar.c | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c index 507e8f2641..43cce231b6 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c @@ -384,7 +384,7 @@ InvalidateIOTLB ( Enable DMAR translation inpre-mem phase. @param[in] VtdUnitBaseAddress The base address of the VTd engine. - @param[in] RootEntryTable The address of the VTd RootEntryTable. + @param[in] RtaddrRegValue The value of RTADDR_REG. @retval EFI_SUCCESS DMAR translation is enabled. @retval EFI_DEVICE_ERROR DMAR translation is not enabled. @@ -392,15 +392,15 @@ InvalidateIOTLB ( EFI_STATUS EnableDmarPreMem ( IN UINTN VtdUnitBaseAddress, - IN UINTN RootEntryTable + IN UINTN RtaddrRegValue ) { UINT32 Reg32; DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUnitBaseAddress)); - DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable)); - MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable); + DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%x \n", RtaddrRegValue)); + MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RtaddrRegValue); Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP); @@ -662,18 +662,6 @@ EnableVTdTranslationProtectionAll ( DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionAll - 0x%lx\n", EngineMask)); - Status = PeiServicesLocatePpi ( - &gEdkiiVTdNullRootEntryTableGuid, - 0, - NULL, - (VOID **)&RootEntryTable - ); - if (EFI_ERROR(Status)) { - DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status)); - ASSERT (FALSE); - return; - } - for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { if ((EngineMask & LShiftU64(1, Index)) == 0) { continue; @@ -686,7 +674,28 @@ EnableVTdTranslationProtectionAll ( VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG); DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg); - EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable); + if (VTdInfo->VtdUnitInfo[Index].ECapReg.Bits.ADMS == 1) { + // + // Use Abort DMA Mode + // + Status = EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM); + } else { + // + // Use Null Root Entry Table + // + Status = PeiServicesLocatePpi ( + &gEdkiiVTdNullRootEntryTableGuid, + 0, + NULL, + (VOID **)&RootEntryTable + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status)); + ASSERT (FALSE); + return; + } + EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable); + } } return; From b387330db21006a7d16d5e5b5a0acc2da26977c4 Mon Sep 17 00:00:00 2001 From: "Sheng, W" Date: Mon, 24 Jan 2022 10:43:48 +0800 Subject: [PATCH 18/26] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once. VTdInfoNotify may be called manay times, PEI DMA buffer should be generated only once. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3667 Reviewed-by: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Cc: Robert Kowalewski Reviewed-by: Jenny Huang Signed-off-by: Sheng Wei --- .../Feature/VTd/IntelVTdDmarPei/DmarTable.c | 549 +----------------- .../VTd/IntelVTdDmarPei/IntelVTdDmar.c | 444 ++++++-------- .../VTd/IntelVTdDmarPei/IntelVTdDmarPei.c | 495 +++++++++------- .../VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 123 ++-- .../VTd/IntelVTdDmarPei/TranslationTable.c | 196 +------ 5 files changed, 559 insertions(+), 1248 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c index 7a08546f0d..010dd549ca 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c @@ -1,6 +1,7 @@ /** @file - Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -104,74 +105,6 @@ DumpDmarDeviceScopeEntry ( return; } -/** - Dump DMAR RMRR table. - - @param[in] Rmrr DMAR RMRR table -**/ -VOID -DumpDmarRmrr ( - IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr - ) -{ - EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry; - INTN RmrrLen; - - if (Rmrr == NULL) { - return; - } - - DEBUG ((DEBUG_INFO, - " ***************************************************************************\n" - )); - DEBUG ((DEBUG_INFO, - " * Reserved Memory Region Reporting Structure *\n" - )); - DEBUG ((DEBUG_INFO, - " ***************************************************************************\n" - )); - DEBUG ((DEBUG_INFO, - (sizeof (UINTN) == sizeof (UINT64)) ? - " RMRR address ........................................... 0x%016lx\n" : - " RMRR address ........................................... 0x%08x\n", - Rmrr - )); - DEBUG ((DEBUG_INFO, - " Type ................................................. 0x%04x\n", - Rmrr->Header.Type - )); - DEBUG ((DEBUG_INFO, - " Length ............................................... 0x%04x\n", - Rmrr->Header.Length - )); - DEBUG ((DEBUG_INFO, - " Segment Number ....................................... 0x%04x\n", - Rmrr->SegmentNumber - )); - DEBUG ((DEBUG_INFO, - " Reserved Memory Region Base Address .................. 0x%016lx\n", - Rmrr->ReservedMemoryRegionBaseAddress - )); - DEBUG ((DEBUG_INFO, - " Reserved Memory Region Limit Address ................. 0x%016lx\n", - Rmrr->ReservedMemoryRegionLimitAddress - )); - - RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER); - DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) (Rmrr + 1); - while (RmrrLen > 0) { - DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); - RmrrLen -= DmarDeviceScopeEntry->Length; - DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length); - } - - DEBUG ((DEBUG_INFO, - " ***************************************************************************\n\n" - )); - - return; -} - /** Dump DMAR DRHD table. @@ -312,9 +245,6 @@ DumpAcpiDMAR ( case EFI_ACPI_DMAR_TYPE_DRHD: DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader); break; - case EFI_ACPI_DMAR_TYPE_RMRR: - DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader); - break; default: break; } @@ -330,491 +260,42 @@ DumpAcpiDMAR ( } /** - Get VTd engine number. + Parse DMAR DRHD table. @param[in] AcpiDmarTable DMAR ACPI table + @param[in] Callback Callback function for handle DRHD + @param[in] Context Callback function Context @return the VTd engine number. + **/ UINTN -GetVtdEngineNumber ( - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable - ) -{ - EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - UINTN VtdIndex; - - VtdIndex = 0; - DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1)); - while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) { - switch (DmarHeader->Type) { - case EFI_ACPI_DMAR_TYPE_DRHD: - VtdIndex++; - break; - default: - break; - } - DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length); - } - return VtdIndex ; -} - -/** - Get PCI device information from DMAR DevScopeEntry. - - @param[in] Segment The segment number. - @param[in] DmarDevScopeEntry DMAR DevScopeEntry - @param[out] Bus The bus number. - @param[out] Device The device number. - @param[out] Function The function number. - - @retval EFI_SUCCESS The PCI device information is returned. -**/ -EFI_STATUS -GetPciBusDeviceFunction ( - IN UINT16 Segment, - IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry, - OUT UINT8 *Bus, - OUT UINT8 *Device, - OUT UINT8 *Function - ) -{ - EFI_ACPI_DMAR_PCI_PATH *DmarPciPath; - UINT8 MyBus; - UINT8 MyDevice; - UINT8 MyFunction; - - DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINTN) (DmarDevScopeEntry + 1)); - MyBus = DmarDevScopeEntry->StartBusNumber; - MyDevice = DmarPciPath->Device; - MyFunction = DmarPciPath->Function; - - switch (DmarDevScopeEntry->Type) { - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT: - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE: - while ((UINTN) DmarPciPath + sizeof (EFI_ACPI_DMAR_PCI_PATH) < (UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length) { - MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET)); - DmarPciPath ++; - MyDevice = DmarPciPath->Device; - MyFunction = DmarPciPath->Function; - } - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC: - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET: - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE: - break; - } - - *Bus = MyBus; - *Device = MyDevice; - *Function = MyFunction; - - return EFI_SUCCESS; -} - -/** - Return the index of PCI data. - - @param[in] VTdUnitInfo The VTd engine unit information. - @param[in] Segment The Segment used to identify a VTd engine. - @param[in] SourceId The SourceId used to identify a VTd engine and table entry. - - @return The index of the PCI data. - @retval (UINTN)-1 The PCI data is not found. -**/ -UINTN -GetPciDataIndex ( - IN VTD_UNIT_INFO *VTdUnitInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId - ) -{ - UINTN Index; - VTD_SOURCE_ID *PciSourceId; - PEI_PCI_DEVICE_DATA *PciDeviceDataBase; - - if (Segment != VTdUnitInfo->Segment) { - return (UINTN)-1; - } - - for (Index = 0; Index < VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber; Index++) { - PciDeviceDataBase = (PEI_PCI_DEVICE_DATA*) (UINTN) VTdUnitInfo->PciDeviceInfo.PciDeviceData; - PciSourceId = &PciDeviceDataBase[Index].PciSourceId; - if ((PciSourceId->Bits.Bus == SourceId.Bits.Bus) && - (PciSourceId->Bits.Device == SourceId.Bits.Device) && - (PciSourceId->Bits.Function == SourceId.Bits.Function) ) { - return Index; - } - } - - return (UINTN)-1; -} - - -/** - Register PCI device to VTd engine. - - @param[in] VTdUnitInfo The VTd engine unit information. - @param[in] Segment The segment of the source. - @param[in] SourceId The SourceId of the source. - @param[in] DeviceType The DMAR device scope type. - @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered. - FALSE: SUCCESS will be returned if the PCI device is registered. - - @retval EFI_SUCCESS The PCI device is registered. - @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device. - @retval EFI_ALREADY_STARTED The device is already registered. - -**/ -EFI_STATUS -RegisterPciDevice ( - IN VTD_UNIT_INFO *VTdUnitInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId, - IN UINT8 DeviceType, - IN BOOLEAN CheckExist - ) -{ - PEI_PCI_DEVICE_INFORMATION *PciDeviceInfo; - VTD_SOURCE_ID *PciSourceId; - UINTN PciDataIndex; - UINTN PciDeviceDataSize; - PEI_PCI_DEVICE_DATA *NewPciDeviceData; - PEI_PCI_DEVICE_DATA *PciDeviceDataBase; - - PciDeviceInfo = &VTdUnitInfo->PciDeviceInfo; - - PciDataIndex = GetPciDataIndex (VTdUnitInfo, Segment, SourceId); - if (PciDataIndex == (UINTN)-1) { - // - // Register new - // - - if (PciDeviceInfo->PciDeviceDataNumber >= PciDeviceInfo->PciDeviceDataMaxNumber) { - // - // Reallocate - // - PciDeviceDataSize = sizeof(*NewPciDeviceData) * (PciDeviceInfo->PciDeviceDataMaxNumber + MAX_VTD_PCI_DATA_NUMBER); - DEBUG ((DEBUG_INFO, "New PciDeviceDataSize:%d Page:%d\n", PciDeviceDataSize, EFI_SIZE_TO_PAGES (PciDeviceDataSize))); - NewPciDeviceData = AllocateZeroPages (EFI_SIZE_TO_PAGES(PciDeviceDataSize)); - if (NewPciDeviceData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - PciDeviceInfo->PciDeviceDataMaxNumber += MAX_VTD_PCI_DATA_NUMBER; - if (PciDeviceInfo->PciDeviceData != 0) { - CopyMem (NewPciDeviceData, (VOID *) (UINTN) PciDeviceInfo->PciDeviceData, sizeof (*NewPciDeviceData) * PciDeviceInfo->PciDeviceDataNumber); - FreePages((VOID *) (UINTN) PciDeviceInfo->PciDeviceData, PciDeviceInfo->PciDeviceDataPageSize); - } - PciDeviceInfo->PciDeviceData = (UINT32) (UINTN) NewPciDeviceData; - PciDeviceInfo->PciDeviceDataPageSize = (UINT32) EFI_SIZE_TO_PAGES (PciDeviceDataSize); - } - - ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceDataMaxNumber); - - PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) PciDeviceInfo->PciDeviceData; - PciSourceId = &PciDeviceDataBase[PciDeviceInfo->PciDeviceDataNumber].PciSourceId; - PciSourceId->Bits.Bus = SourceId.Bits.Bus; - PciSourceId->Bits.Device = SourceId.Bits.Device; - PciSourceId->Bits.Function = SourceId.Bits.Function; - - DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - - PciDeviceDataBase[PciDeviceInfo->PciDeviceDataNumber].DeviceType = DeviceType; - - if ((DeviceType != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) && - (DeviceType != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) { - DEBUG ((DEBUG_INFO, " (*)")); - } - DEBUG ((DEBUG_INFO, "\n")); - - PciDeviceInfo->PciDeviceDataNumber++; - } else { - if (CheckExist) { - DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x already registered\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - return EFI_ALREADY_STARTED; - } - } - - return EFI_SUCCESS; -} - -/** - Process DMAR DRHD table. - - @param[in] VTdUnitInfo The VTd engine unit information. - @param[in] DmarDrhd The DRHD table. - -**/ -VOID -ProcessDrhd ( - IN VTD_UNIT_INFO *VTdUnitInfo, - IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd - ) -{ - EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry; - UINT8 Bus; - UINT8 Device; - UINT8 Function; - EFI_STATUS Status; - VTD_SOURCE_ID SourceId; - - DEBUG ((DEBUG_INFO," VTD BaseAddress - 0x%016lx\n", DmarDrhd->RegisterBaseAddress)); - VTdUnitInfo->VtdUnitBaseAddress = (UINT32) DmarDrhd->RegisterBaseAddress; - - VTdUnitInfo->EnableQueuedInvalidation = 0; - - DEBUG ((DEBUG_INFO," VTD Segment - %d\n", DmarDrhd->SegmentNumber)); - VTdUnitInfo->Segment = DmarDrhd->SegmentNumber; - - VTdUnitInfo->FixedSecondLevelPagingEntry = 0; - VTdUnitInfo->RmrrSecondLevelPagingEntry = 0; - VTdUnitInfo->RootEntryTable = 0; - VTdUnitInfo->ExtRootEntryTable = 0; - VTdUnitInfo->RootEntryTablePageSize = 0; - VTdUnitInfo->ExtRootEntryTablePageSize = 0; - - VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0; - - if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) { - VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = TRUE; - DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n")); - } else { - VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE; - DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n")); - } - - VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0; - VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0; - - DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarDrhd + 1)); - while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd->Header.Length) { - - Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function); - if (EFI_ERROR (Status)) { - return; - } - - DEBUG ((DEBUG_INFO," ProcessDrhd: ")); - switch (DmarDevScopeEntry->Type) { - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT: - DEBUG ((DEBUG_INFO,"PCI Endpoint")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE: - DEBUG ((DEBUG_INFO,"PCI-PCI bridge")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC: - DEBUG ((DEBUG_INFO,"IOAPIC")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET: - DEBUG ((DEBUG_INFO,"MSI Capable HPET")); - break; - case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE: - DEBUG ((DEBUG_INFO,"ACPI Namespace Device")); - break; - } - DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumber, Bus, Device, Function)); - - SourceId.Bits.Bus = Bus; - SourceId.Bits.Device = Device; - SourceId.Bits.Function = Function; - - Status = RegisterPciDevice (VTdUnitInfo, DmarDrhd->SegmentNumber, SourceId, DmarDevScopeEntry->Type, TRUE); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n")); - } - - DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length); - } -} - -/** - Dump the PCI device information managed by this VTd engine. - - @param[in] VTdInfo The VTd engine context information. - @param[in] VtdIndex The index of VTd engine. - -**/ -VOID -DumpPciDeviceInfo ( - IN VTD_INFO *VTdInfo, - IN UINTN VtdIndex - ) -{ - UINTN Index; - PEI_PCI_DEVICE_DATA *PciDeviceDataBase; - - DEBUG ((DEBUG_INFO,"PCI Device Information (Number 0x%x, IncludeAll - %d):\n", - VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceDataNumber, - VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.IncludeAllFlag - )); - - PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData; - - for (Index = 0; Index < VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; Index++) { - DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", - VTdInfo->VtdUnitInfo[VtdIndex].Segment, - PciDeviceDataBase[Index].PciSourceId.Bits.Bus, - PciDeviceDataBase[Index].PciSourceId.Bits.Device, - PciDeviceDataBase[Index].PciSourceId.Bits.Function - )); - } -} - -/** - Parse DMAR DRHD table. - - @param[in] AcpiDmarTable DMAR ACPI table - - @return EFI_SUCCESS The DMAR DRHD table is parsed. - -**/ -EFI_STATUS ParseDmarAcpiTableDrhd ( - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable, + IN PROCESS_DRHD_CALLBACK_FUNC Callback, + IN VOID *Context ) { EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - UINTN VtdUnitNumber; UINTN VtdIndex; - VTD_INFO *VTdInfo; - - VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable); - if (VtdUnitNumber == 0) { - return EFI_UNSUPPORTED; - } - - VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO) + (VtdUnitNumber - 1) * sizeof (VTD_UNIT_INFO)); - ASSERT(VTdInfo != NULL); - if (VTdInfo == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - // - // Initialize the engine mask to all. - // - VTdInfo->AcpiDmarTable = (UINT32) (UINTN) AcpiDmarTable; - VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth; - VTdInfo->VTdEngineCount = (UINT32) VtdUnitNumber; VtdIndex = 0; DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1)); + while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) { switch (DmarHeader->Type) { case EFI_ACPI_DMAR_TYPE_DRHD: - ASSERT (VtdIndex < VtdUnitNumber); - ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader); + if (Callback != NULL) { + Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader); + } VtdIndex++; - - break; - - default: - break; - } - DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length); - } - ASSERT (VtdIndex == VtdUnitNumber); - - for (VtdIndex = 0; VtdIndex < VtdUnitNumber; VtdIndex++) { - DumpPciDeviceInfo (VTdInfo, VtdIndex); - } - - return EFI_SUCCESS; -} - - -/** - Process DMAR RMRR table. - - @param[in] VTdInfo The VTd engine context information. - @param[in] DmarRmrr The RMRR table. - -**/ -VOID -ProcessRmrr ( - IN VTD_INFO *VTdInfo, - IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr - ) -{ - EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry; - UINT8 Bus; - UINT8 Device; - UINT8 Function; - EFI_STATUS Status; - VTD_SOURCE_ID SourceId; - - DEBUG ((DEBUG_INFO," PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress)); - - if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) || - (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) { - return ; - } - - DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarRmrr + 1)); - while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr->Header.Length) { - if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) { - DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%x] \n", DmarDevScopeEntry->Type)); - return; - } - - Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function); - if (EFI_ERROR (Status)) { - continue; - } - - DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function)); - - SourceId.Bits.Bus = Bus; - SourceId.Bits.Device = Device; - SourceId.Bits.Function = Function; - - Status = EnableRmrrPageAttribute ( - VTdInfo, - DmarRmrr->SegmentNumber, - SourceId, - DmarRmrr->ReservedMemoryRegionBaseAddress, - DmarRmrr->ReservedMemoryRegionLimitAddress, - EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "EnableRmrrPageAttribute : %r\n", Status)); - } - - DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length); - } -} - -/** - Parse DMAR DRHD table. - - @param[in] VTdInfo The VTd engine context information. - -**/ -VOID -ParseDmarAcpiTableRmrr ( - IN VTD_INFO *VTdInfo - ) -{ - EFI_ACPI_DMAR_HEADER *AcpiDmarTable; - EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - - AcpiDmarTable = (EFI_ACPI_DMAR_HEADER *) (UINTN) VTdInfo->AcpiDmarTable; - - DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1)); - while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) { - switch (DmarHeader->Type) { - case EFI_ACPI_DMAR_TYPE_RMRR: - ProcessRmrr (VTdInfo, (EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader); break; default: break; } DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length); } + + return VtdIndex; } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c index 43cce231b6..41db207367 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -79,77 +79,73 @@ PerpareCacheInvalidationInterface ( IN VTD_UNIT_INFO *VTdUnitInfo ) { - UINT16 QueueSize; + UINT16 QiDescLength; UINT64 Reg64; UINT32 Reg32; VTD_ECAP_REG ECapReg; + UINTN VtdUnitBaseAddress; + VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress; - if (VTdUnitInfo->VerReg.Bits.Major <= 6) { + if (VTdUnitInfo->VerReg.Bits.Major <= 5) { VTdUnitInfo->EnableQueuedInvalidation = 0; - DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress)); + DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress)); return EFI_SUCCESS; } - ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG); + ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG); if (ECapReg.Bits.QI == 0) { - DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress)); + DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VtdUnitBaseAddress)); return EFI_UNSUPPORTED; } VTdUnitInfo->EnableQueuedInvalidation = 1; - DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress)); + DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress)); - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); if ((Reg32 & B_GSTS_REG_QIES) != 0) { DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n")); Reg32 &= (~B_GSTS_REG_QIES); - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32); + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32); do { - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) != 0); - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, 0); - - if (VTdUnitInfo->QiDesc != NULL) { - FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength)); - VTdUnitInfo->QiDesc = NULL; - VTdUnitInfo->QiDescLength = 0; - } + MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, 0); } // // Initialize the Invalidation Queue Tail Register to zero. // - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, 0); + MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0); // // Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register // - QueueSize = 0; - VTdUnitInfo->QiDescLength = 1 << (QueueSize + 8); - VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength)); - if (VTdUnitInfo->QiDesc == NULL) { - VTdUnitInfo->QiDescLength = 0; - DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); - return EFI_OUT_OF_RESOURCES; + VTdUnitInfo->QueueSize = 0; + QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); + VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength)); + if (VTdUnitInfo->QiDesc == NULL) { + DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); + return EFI_OUT_OF_RESOURCES; + } } - DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", VTdUnitInfo->QiDescLength)); - Reg64 = (UINT64)(UINTN)VTdUnitInfo->QiDesc; - Reg64 |= QueueSize; - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, Reg64); + DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", QiDescLength)); + Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc; + Reg64 |= VTdUnitInfo->QueueSize; + MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64); // // Enable the queued invalidation interface through the Global Command Register. // When enabled, hardware sets the QIES field in the Global Status Register. // - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); Reg32 |= B_GMCD_REG_QIE; - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32); + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32); DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32)); do { - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) == 0); VTdUnitInfo->QiFreeHead = 0; @@ -167,21 +163,23 @@ DisableQueuedInvalidationInterface ( IN VTD_UNIT_INFO *VTdUnitInfo ) { - UINT32 Reg32; + UINT32 Reg32; + UINT16 QiDescLength; if (VTdUnitInfo->EnableQueuedInvalidation != 0) { - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); Reg32 &= (~B_GMCD_REG_QIE); - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32); + MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32); DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32)); do { - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_QIES) != 0); if (VTdUnitInfo->QiDesc != NULL) { - FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength)); + QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); + FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength)); VTdUnitInfo->QiDesc = NULL; - VTdUnitInfo->QiDescLength = 0; + VTdUnitInfo->QueueSize = 0; } VTdUnitInfo->EnableQueuedInvalidation = 0; @@ -203,26 +201,11 @@ QueuedInvalidationCheckFault ( { UINT32 FaultReg; - FaultReg = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG); - - if (FaultReg & B_FSTS_REG_IQE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", FaultReg)); - FaultReg |= B_FSTS_REG_IQE; - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); - return RETURN_DEVICE_ERROR; - } - - if (FaultReg & B_FSTS_REG_ITE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", FaultReg)); - FaultReg |= B_FSTS_REG_ITE; - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); - return RETURN_DEVICE_ERROR; - } - - if (FaultReg & B_FSTS_REG_ICE) { - DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n", FaultReg)); - FaultReg |= B_FSTS_REG_ICE; - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); + FaultReg = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG); + if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) { + DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", FaultReg)); + FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE); + MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg); return RETURN_DEVICE_ERROR; } @@ -256,7 +239,7 @@ SubmitQueuedInvalidationDescriptor ( return EFI_INVALID_PARAMETER; } - QiDescLength = VTdUnitInfo->QiDescLength; + QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); BaseDesc = VTdUnitInfo->QiDesc; DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%08x, 0x%08x]\n", VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High)); @@ -268,12 +251,12 @@ SubmitQueuedInvalidationDescriptor ( DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead)); VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) % QiDescLength; - Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG); + Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG); // // Update the HW tail register indicating the presence of new descriptors. // Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT; - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt); + MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt); Status = EFI_SUCCESS; do { @@ -283,7 +266,7 @@ SubmitQueuedInvalidationDescriptor ( break; } - Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG); + Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG); } while (Reg64Iqt != Reg64Iqh); DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n")); @@ -307,18 +290,18 @@ InvalidateContextCache ( // // Register-based Invalidation // - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG); + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG); if ((Reg64 & B_CCMD_REG_ICC) != 0) { - DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress)); + DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", VTdUnitInfo->VtdUnitBaseAddress)); return EFI_DEVICE_ERROR; } Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK)); Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL); - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64); + MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64); do { - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG); + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG); } while ((Reg64 & B_CCMD_REG_ICC) != 0); } else { // @@ -351,26 +334,26 @@ InvalidateIOTLB ( // // Register-based Invalidation // - ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG); + ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG); - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG); + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG); if ((Reg64 & B_IOTLB_REG_IVT) != 0) { - DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", (UINTN)VTdUnitInfo->VtdUnitBaseAddress)); + DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VTdUnitInfo->VtdUnitBaseAddress)); return EFI_DEVICE_ERROR; } Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK)); Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL); - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64); + MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64); do { - Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG); + Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG); } while ((Reg64 & B_IOTLB_REG_IVT) != 0); } else { // // Queued Invalidation // - ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG); + ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG); QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(ECapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(ECapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE; QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0); @@ -392,15 +375,15 @@ InvalidateIOTLB ( EFI_STATUS EnableDmarPreMem ( IN UINTN VtdUnitBaseAddress, - IN UINTN RtaddrRegValue + IN UINT64 RtaddrRegValue ) { UINT32 Reg32; DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUnitBaseAddress)); - DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%x \n", RtaddrRegValue)); - MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RtaddrRegValue); + DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue)); + MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, RtaddrRegValue); Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP); @@ -452,30 +435,33 @@ EnableDmar ( ) { UINT32 Reg32; + UINTN VtdUnitBaseAddress; - DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VTdUnitInfo->VtdUnitBaseAddress)); + VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress; + + DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress)); DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable)); - MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable); + MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable); - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP); DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n")); do { - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while((Reg32 & B_GSTS_REG_RTPS) == 0); DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32)); // // Init DMAr Fault Event and Data registers // - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FEDATA_REG); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG); // // Write Buffer Flush before invalidation // - FlushWriteBuffer ((UINTN)VTdUnitInfo->VtdUnitBaseAddress); + FlushWriteBuffer (VtdUnitBaseAddress); // // Invalidate the context cache @@ -490,11 +476,11 @@ EnableDmar ( // // Enable VTd // - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); - MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE); DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n")); do { - Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); + Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); } while ((Reg32 & B_GSTS_REG_TE) == 0); DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n")); @@ -566,139 +552,52 @@ DisableDmar ( } /** - Dump VTd version registers. + Enable VTd translation table protection for block DMA - @param[in] VerReg The version register. + @param[in] VtdUnitBaseAddress The base address of the VTd engine. + + @retval EFI_SUCCESS DMAR translation is enabled. + @retval EFI_DEVICE_ERROR DMAR translation is not enabled. **/ -VOID -DumpVtdVerRegs ( - IN VTD_VER_REG *VerReg +EFI_STATUS +EnableVTdTranslationProtectionBlockDma ( + IN UINTN VtdUnitBaseAddress ) { - DEBUG ((DEBUG_INFO, " VerReg:\n", VerReg->Uint32)); - DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major)); - DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor)); -} + EFI_STATUS Status; + VTD_ECAP_REG ECapReg; + EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI *RootEntryTable; -/** - Dump VTd capability registers. + DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n", VtdUnitBaseAddress)); - @param[in] CapReg The capability register. -**/ -VOID -DumpVtdCapRegs ( - IN VTD_CAP_REG *CapReg - ) -{ - DEBUG ((DEBUG_INFO, " CapReg:\n", CapReg->Uint64)); - DEBUG ((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND)); - DEBUG ((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL)); - DEBUG ((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF)); - DEBUG ((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR)); - DEBUG ((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR)); - DEBUG ((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM)); - DEBUG ((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW)); - DEBUG ((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW)); - DEBUG ((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR)); - DEBUG ((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO)); - DEBUG ((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS)); - DEBUG ((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI)); - DEBUG ((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR)); - DEBUG ((DEBUG_INFO, " MAMV - 0x%x\n", CapReg->Bits.MAMV)); - DEBUG ((DEBUG_INFO, " DWD - 0x%x\n", CapReg->Bits.DWD)); - DEBUG ((DEBUG_INFO, " DRD - 0x%x\n", CapReg->Bits.DRD)); - DEBUG ((DEBUG_INFO, " FL1GP - 0x%x\n", CapReg->Bits.FL1GP)); - DEBUG ((DEBUG_INFO, " PI - 0x%x\n", CapReg->Bits.PI)); -} + ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG); + DEBUG ((DEBUG_INFO, "ECapReg : 0%016lx\n", ECapReg.Uint64)); -/** - Dump VTd extended capability registers. - - @param[in] ECapReg The extended capability register. -**/ -VOID -DumpVtdECapRegs ( - IN VTD_ECAP_REG *ECapReg - ) -{ - DEBUG ((DEBUG_INFO, " ECapReg:\n", ECapReg->Uint64)); - DEBUG ((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C)); - DEBUG ((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI)); - DEBUG ((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT)); - DEBUG ((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR)); - DEBUG ((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM)); - DEBUG ((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT)); - DEBUG ((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC)); - DEBUG ((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO)); - DEBUG ((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV)); - DEBUG ((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS)); - DEBUG ((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST)); - DEBUG ((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID)); - DEBUG ((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS)); - DEBUG ((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS)); - DEBUG ((DEBUG_INFO, " SRS - 0x%x\n", ECapReg->Bits.SRS)); - DEBUG ((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS)); - DEBUG ((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS)); - DEBUG ((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS)); - DEBUG ((DEBUG_INFO, " ADMS - 0x%x\n", ECapReg->Bits.ADMS)); -} - - -/** - Enable VTd translation table protection for all. - - @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. -**/ -VOID -EnableVTdTranslationProtectionAll ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask - ) -{ - EFI_STATUS Status; - EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI *RootEntryTable; - UINTN Index; - - DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionAll - 0x%lx\n", EngineMask)); - - for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - if ((EngineMask & LShiftU64(1, Index)) == 0) { - continue; - } - - VTdInfo->VtdUnitInfo[Index].VerReg.Uint32 = MmioRead32 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_VER_REG); - DumpVtdVerRegs (&VTdInfo->VtdUnitInfo[Index].VerReg); - VTdInfo->VtdUnitInfo[Index].CapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_CAP_REG); - DumpVtdCapRegs (&VTdInfo->VtdUnitInfo[Index].CapReg); - VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG); - DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg); - - if (VTdInfo->VtdUnitInfo[Index].ECapReg.Bits.ADMS == 1) { - // - // Use Abort DMA Mode - // - Status = EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM); - } else { - // - // Use Null Root Entry Table - // - Status = PeiServicesLocatePpi ( - &gEdkiiVTdNullRootEntryTableGuid, - 0, - NULL, - (VOID **)&RootEntryTable - ); - if (EFI_ERROR(Status)) { - DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status)); - ASSERT (FALSE); - return; - } - EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable); + if (ECapReg.Bits.ADMS == 1) { + // + // Use Abort DMA Mode + // + DEBUG ((DEBUG_INFO, "Enable abort DMA mode.\n")); + Status = EnableDmarPreMem (VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM); + } else { + // + // Use Null Root Entry Table + // + Status = PeiServicesLocatePpi ( + &gEdkiiVTdNullRootEntryTableGuid, + 0, + NULL, + (VOID **)&RootEntryTable + ); + if (EFI_ERROR(Status)) { + DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status)); + ASSERT (FALSE); + return EFI_DEVICE_ERROR; } + Status = EnableDmarPreMem (VtdUnitBaseAddress, (UINT64) (*RootEntryTable)); } - return; + return Status; } /** @@ -715,20 +614,28 @@ EnableVTdTranslationProtection ( ) { EFI_STATUS Status; - UINTN VtdIndex; + UINTN Index; + VTD_UNIT_INFO *VtdUnitInfo; - for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) { - if (VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable != 0) { - DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable)); - Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex], VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable); + for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { + VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index]; + if (VtdUnitInfo->Done) { + DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index)); + continue; + } + + if (VtdUnitInfo->ExtRootEntryTable != 0) { + DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", Index, VtdUnitInfo->ExtRootEntryTable)); + Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable); } else { - DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable)); - Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex], VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable); + DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", Index, VtdUnitInfo->RootEntryTable)); + Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->RootEntryTable); } if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", VtdIndex)); + DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", Index)); return Status; } + VtdUnitInfo->Done = TRUE; } return EFI_SUCCESS; } @@ -737,23 +644,22 @@ EnableVTdTranslationProtection ( Disable VTd translation table protection. @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. **/ VOID DisableVTdTranslationProtection ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask + IN VTD_INFO *VTdInfo ) { UINTN Index; - DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask)); + if (VTdInfo == NULL) { + return; + } + + DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - %d Vtd Engine\n", VTdInfo->VTdEngineCount)); for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - if ((EngineMask & LShiftU64(1, Index)) == 0) { - continue; - } - DisableDmar ((UINTN) VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress); + DisableDmar (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress); DisableQueuedInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]); } @@ -786,6 +692,44 @@ PrepareVtdCacheInvalidationConfig ( return EFI_SUCCESS; } +/** + Check if VTd engine use 5 level paging. + + @param[in] HostAddressWidth Host Address Width. + @param[in] VtdUnitInfo The VTd engine unit information. + @param[out] Is5LevelPaging Use 5 level paging or not + + @retval EFI_SUCCESS Success + @retval EFI_UNSUPPORTED Feature is not support + +**/ +EFI_STATUS +VtdCheckUsing5LevelPaging ( + IN UINT8 HostAddressWidth, + IN VTD_UNIT_INFO *VtdUnitInfo, + OUT BOOLEAN *Is5LevelPaging + ) +{ + DEBUG((DEBUG_INFO, " CapReg SAGAW bits : 0x%02x\n", VtdUnitInfo->CapReg.Bits.SAGAW)); + + *Is5LevelPaging = FALSE; + if ((VtdUnitInfo->CapReg.Bits.SAGAW & BIT3) != 0) { + *Is5LevelPaging = TRUE; + if ((HostAddressWidth <= 48) && + ((VtdUnitInfo->CapReg.Bits.SAGAW & BIT2) != 0)) { + *Is5LevelPaging = FALSE; + } else { + return EFI_UNSUPPORTED; + } + } + if ((VtdUnitInfo->CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) { + return EFI_UNSUPPORTED; + } + DEBUG((DEBUG_INFO, " Using %d Level Paging\n", *Is5LevelPaging ? 5 : 4)); + return EFI_SUCCESS; +} + + /** Prepare VTD configuration. @@ -798,43 +742,37 @@ PrepareVtdConfig ( IN VTD_INFO *VTdInfo ) { + EFI_STATUS Status; UINTN Index; - UINTN DomainNumber; + VTD_UNIT_INFO *VtdUnitInfo; + UINTN VtdUnitBaseAddress; for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - DEBUG ((DEBUG_ERROR, "Dump VTd Capability (%d)\n", Index)); - VTdInfo->VtdUnitInfo[Index].VerReg.Uint32 = MmioRead32 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_VER_REG); - DumpVtdVerRegs (&VTdInfo->VtdUnitInfo[Index].VerReg); - VTdInfo->VtdUnitInfo[Index].CapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_CAP_REG); - DumpVtdCapRegs (&VTdInfo->VtdUnitInfo[Index].CapReg); - VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG); - DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg); - - VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = FALSE; - if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT2) != 0) { - DEBUG ((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index)); + VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index]; + if (VtdUnitInfo->Done) { + continue; } - if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT3) != 0) { - DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index)); - VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = TRUE; + VtdUnitBaseAddress = VtdUnitInfo->VtdUnitBaseAddress; + DEBUG((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitBaseAddress)); - if ((VTdInfo->HostAddressWidth <= 48) && - ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT2) != 0)) { - DEBUG ((DEBUG_INFO, "Rollback to 4-level page-table on VTD %d\n", Index)); - VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = FALSE; - } - } - if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) { - DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on VTD %d !!!!\n", Index, VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW)); - return EFI_UNSUPPORTED; + VtdUnitInfo->VerReg.Uint32 = MmioRead32 (VtdUnitBaseAddress + R_VER_REG); + VtdUnitInfo->CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG); + VtdUnitInfo->ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG); + DEBUG((DEBUG_INFO, " VerReg : 0x%08X\n", VtdUnitInfo->VerReg.Uint32)); + DEBUG((DEBUG_INFO, " CapReg : 0x%016lX\n", VtdUnitInfo->CapReg.Uint64)); + DEBUG((DEBUG_INFO, " ECapReg : 0x%016lX\n", VtdUnitInfo->ECapReg.Uint64)); + + Status = VtdCheckUsing5LevelPaging (VTdInfo->HostAddressWidth, VtdUnitInfo, &(VtdUnitInfo->Is5LevelPaging)); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported!!!!\n", VtdUnitInfo->CapReg.Bits.SAGAW)); + return Status; } - DomainNumber = (UINTN)1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[Index].CapReg.Bits.ND * 2 + 4); - if (VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber >= DomainNumber) { - DEBUG ((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber, DomainNumber)); - return EFI_UNSUPPORTED; + Status = PerpareCacheInvalidationInterface(VtdUnitInfo); + if (EFI_ERROR (Status)) { + return Status; } } + return EFI_SUCCESS; } - diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c index a5f61ae5ae..c883d398cc 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2020, Intel Corporation. All rights reserved.
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -23,6 +23,8 @@ #include #include "IntelVTdDmarPei.h" +#define VTD_UNIT_MAX 42 + EFI_GUID mVTdInfoGuid = { 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 } }; @@ -50,20 +52,20 @@ typedef struct { the device driver need use SetAttribute() to update the IOMMU attribute to request DMA access (read and/or write). - @param[in] This The PPI instance pointer. - @param[in] DeviceHandle The device who initiates the DMA access request. - @param[in] Mapping The mapping value returned from Map(). - @param[in] IoMmuAccess The IOMMU access. + @param[in] This The PPI instance pointer. + @param[in] DeviceHandle The device who initiates the DMA access request. + @param[in] Mapping The mapping value returned from Map(). + @param[in] IoMmuAccess The IOMMU access. - @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length. - @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). - @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access. - @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU. - @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping. - @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access. - @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access. + @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU. + @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access. + @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -93,22 +95,22 @@ PeiIoMmuSetAttribute ( Provides the controller-specific addresses required to access system memory from a DMA bus master. - @param This The PPI instance pointer. - @param Operation Indicates if the bus master is going to read or write to system memory. - @param HostAddress The system memory address to map to the PCI controller. - @param NumberOfBytes On input the number of bytes to map. On output the number of bytes - that were mapped. - @param DeviceAddress The resulting map address for the bus master PCI controller to use to - access the hosts HostAddress. - @param Mapping A resulting value to pass to Unmap(). + @param [in] This The PPI instance pointer. + @param [in] Operation Indicates if the bus master is going to read or write to system memory. + @param [in] HostAddress The system memory address to map to the PCI controller. + @param [in] [out] NumberOfBytes On input the number of bytes to map. On output the number of bytes + that were mapped. + @param [out] DeviceAddress The resulting map address for the bus master PCI controller to use to + access the hosts HostAddress. + @param [out] Mapping A resulting value to pass to Unmap(). - @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. - @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. - @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -140,7 +142,7 @@ PeiIoMmuMap ( if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer || Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) { - *DeviceAddress = (UINTN)HostAddress; + *DeviceAddress = (UINTN) HostAddress; *Mapping = NULL; return EFI_SUCCESS; } @@ -184,14 +186,14 @@ PeiIoMmuMap ( /** Completes the Map() operation and releases any corresponding resources. - @param This The PPI instance pointer. - @param Mapping The mapping value returned from Map(). + @param [in] This The PPI instance pointer. + @param [in] Mapping The mapping value returned from Map(). - @retval EFI_SUCCESS The range was unmapped. - @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). - @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map(). + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -250,21 +252,21 @@ PeiIoMmuUnmap ( Allocates pages that are suitable for an OperationBusMasterCommonBuffer or OperationBusMasterCommonBuffer64 mapping. - @param This The PPI instance pointer. - @param MemoryType The type of memory to allocate, EfiBootServicesData or - EfiRuntimeServicesData. - @param Pages The number of pages to allocate. - @param HostAddress A pointer to store the base system memory address of the - allocated range. - @param Attributes The requested bit mask of attributes for the allocated range. + @param [in] This The PPI instance pointer. + @param [in] MemoryType The type of memory to allocate, EfiBootServicesData or + EfiRuntimeServicesData. + @param [in] Pages The number of pages to allocate. + @param [in] [out] HostAddress A pointer to store the base system memory address of the + allocated range. + @param [in] Attributes The requested bit mask of attributes for the allocated range. - @retval EFI_SUCCESS The requested memory pages were allocated. - @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are - MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE. - @retval EFI_INVALID_PARAMETER One or more parameters are invalid. - @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are + MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -307,15 +309,15 @@ PeiIoMmuAllocateBuffer ( /** Frees memory that was allocated with AllocateBuffer(). - @param This The PPI instance pointer. - @param Pages The number of pages to free. - @param HostAddress The base system memory address of the allocated range. + @param [in] This The PPI instance pointer. + @param [in] Pages The number of pages to free. + @param [in] HostAddress The base system memory address of the allocated range. - @retval EFI_SUCCESS The requested memory pages were freed. - @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages - was not allocated with AllocateBuffer(). - @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are - not available to be allocated yet. + @retval EFI_SUCCESS The requested memory pages were freed. + @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages + was not allocated with AllocateBuffer(). + @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are + not available to be allocated yet. **/ EFI_STATUS EFIAPI @@ -364,52 +366,136 @@ CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = { }; /** - Release the momery in the Intel VTd Info + Get ACPI DMAT Table from EdkiiVTdInfo PPI - @param[in] VTdInfo The VTd engine context information. + @retval Address ACPI DMAT Table address + @retval NULL Failed to get ACPI DMAT Table **/ -VOID -ReleaseVTdInfo ( - IN VTD_INFO *VTdInfo +EFI_ACPI_DMAR_HEADER * GetAcpiDmarTable ( + VOID ) { - UINTN Index; + EFI_STATUS Status; + EFI_ACPI_DMAR_HEADER *AcpiDmarTable; - for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { - DEBUG ((DEBUG_INFO, "Release momery in VTdInfo[%d]\n", Index)); - - if (VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry, 1); - VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry = 0; - } - - if (VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry, 1); - VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry = 0; - } - - if (VTdInfo->VtdUnitInfo[Index].RootEntryTable) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].RootEntryTable, VTdInfo->VtdUnitInfo[Index].RootEntryTablePageSize); - VTdInfo->VtdUnitInfo[Index].RootEntryTable = 0; - } - - if (VTdInfo->VtdUnitInfo[Index].ExtRootEntryTable) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].ExtRootEntryTable, VTdInfo->VtdUnitInfo[Index].ExtRootEntryTablePageSize); - VTdInfo->VtdUnitInfo[Index].RootEntryTable = 0; - } - - if (VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData) { - FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData, VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataPageSize); - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataPageSize = 0; - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData = 0; - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber = 0; - VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataMaxNumber = 0; - } + // + // Get the DMAR table + // + Status = PeiServicesLocatePpi ( + &gEdkiiVTdInfoPpiGuid, + 0, + NULL, + (VOID **)&AcpiDmarTable + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to get ACPI DMAR Table : %r\n", Status)); + AcpiDmarTable = NULL; + } else { + DumpAcpiDMAR (AcpiDmarTable); } + + return AcpiDmarTable; } /** - Initializes the Intel VTd Info. + Get the VTd engine context information hob. + + @retval The VTd engine context information. + +**/ +VTD_INFO * +GetVTdInfoHob ( + VOID + ) +{ + VOID *Hob; + VTD_INFO *VTdInfo; + + Hob = GetFirstGuidHob (&mVTdInfoGuid); + if (Hob == NULL) { + VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO)); + if (VTdInfo != NULL) { + ZeroMem (VTdInfo, sizeof (VTD_INFO)); + } + } else { + VTdInfo = GET_GUID_HOB_DATA(Hob); + } + return VTdInfo; +} + +/** + Callback function of parse DMAR DRHD table in pre-memory phase. + + @param [in] [out] Context Callback function context. + @param [in] VTdIndex The VTd engine index. + @param [in] DmarDrhd The DRHD table. + +**/ +VOID +ProcessDhrdPreMemory ( + IN OUT VOID *Context, + IN UINT32 VTdIndex, + IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd + ) +{ + DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, DmarDrhd->RegisterBaseAddress)); + + EnableVTdTranslationProtectionBlockDma ((UINTN) DmarDrhd->RegisterBaseAddress); +} + +/** + Callback function of parse DMAR DRHD table in post memory phase. + + @param [in] [out] Context Callback function context. + @param [in] VTdIndex The VTd engine index. + @param [in] DmarDrhd The DRHD table. + +**/ +VOID +ProcessDrhdPostMemory ( + IN OUT VOID *Context, + IN UINT32 VTdIndex, + IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd + ) +{ + VTD_UNIT_INFO *VtdUnitInfo; + UINTN Index; + + VtdUnitInfo = (VTD_UNIT_INFO *) Context; + + if (DmarDrhd->RegisterBaseAddress == 0) { + DEBUG ((DEBUG_INFO,"VTd Base Address is 0\n")); + ASSERT (FALSE); + return; + } + + for (Index = 0; Index < VTD_UNIT_MAX; Index++) { + if (VtdUnitInfo[Index].VtdUnitBaseAddress == DmarDrhd->RegisterBaseAddress) { + DEBUG ((DEBUG_INFO,"Find VTD (%d) [0x%08x] Exist\n", VTdIndex, DmarDrhd->RegisterBaseAddress)); + return; + } + } + + for (VTdIndex = 0; VTdIndex < VTD_UNIT_MAX; VTdIndex++) { + if (VtdUnitInfo[VTdIndex].VtdUnitBaseAddress == 0) { + VtdUnitInfo[VTdIndex].VtdUnitBaseAddress = (UINTN) DmarDrhd->RegisterBaseAddress; + VtdUnitInfo[VTdIndex].Segment = DmarDrhd->SegmentNumber; + VtdUnitInfo[VTdIndex].Flags = DmarDrhd->Flags; + VtdUnitInfo[VTdIndex].Done = FALSE; + + DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, DmarDrhd->RegisterBaseAddress)); + DEBUG ((DEBUG_INFO," Segment - %d, Flags - 0x%x\n", DmarDrhd->SegmentNumber, DmarDrhd->Flags)); + return; + } + } + + DEBUG ((DEBUG_INFO,"VtdUnitInfo Table is full\n")); + ASSERT (FALSE); + return; +} + +/** + Initializes the Intel VTd Info in post memory phase. @retval EFI_SUCCESS Usb bot driver is successfully initialized. @retval EFI_OUT_OF_RESOURCES Can't initialize the driver. @@ -419,89 +505,82 @@ InitVTdInfo ( VOID ) { - EFI_STATUS Status; - EFI_ACPI_DMAR_HEADER *AcpiDmarTable; - VOID *Hob; VTD_INFO *VTdInfo; - UINT64 EngineMask; + EFI_ACPI_DMAR_HEADER *AcpiDmarTable; + UINTN VtdUnitNumber; + VTD_UNIT_INFO *VtdUnitInfo; - Status = PeiServicesLocatePpi ( - &gEdkiiVTdInfoPpiGuid, - 0, - NULL, - (VOID **)&AcpiDmarTable - ); - ASSERT_EFI_ERROR (Status); + VTdInfo = GetVTdInfoHob (); + ASSERT (VTdInfo != NULL); - DumpAcpiDMAR (AcpiDmarTable); + AcpiDmarTable = GetAcpiDmarTable (); + ASSERT (AcpiDmarTable != NULL); - // - // Clear old VTdInfo Hob. - // - Hob = GetFirstGuidHob (&mVTdInfoGuid); - if (Hob != NULL) { - DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob)); + if (VTdInfo->VtdUnitInfo == NULL) { + // + // Genrate a new Vtd Unit Info Table + // + VTdInfo->VtdUnitInfo = AllocateZeroPages (EFI_SIZE_TO_PAGES (sizeof (VTD_UNIT_INFO) * VTD_UNIT_MAX)); + if (VTdInfo->VtdUnitInfo == NULL) { + DEBUG ((DEBUG_ERROR, "InitVTdInfo - OUT_OF_RESOURCE\n")); + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + } + VtdUnitInfo = VTdInfo->VtdUnitInfo; - VTdInfo = GET_GUID_HOB_DATA(Hob); - EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1; - EnableVTdTranslationProtectionAll (VTdInfo, EngineMask); + if (VTdInfo->HostAddressWidth == 0) { + VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth; + } - ReleaseVTdInfo (VTdInfo); - VTdInfo->VTdEngineCount = 0; - - ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID)); + if (VTdInfo->HostAddressWidth != AcpiDmarTable->HostAddressWidth) { + DEBUG ((DEBUG_ERROR, "Host Address Width is not match.\n")); + ASSERT (FALSE); + return EFI_UNSUPPORTED; } // - // Get DMAR information to local VTdInfo + // Parse the DMAR ACPI Table to the new Vtd Unit Info Table // - Status = ParseDmarAcpiTableDrhd (AcpiDmarTable); - if (EFI_ERROR(Status)) { - DEBUG ((DEBUG_ERROR, " ParseDmarAcpiTableDrhd : %r\n", Status)); - return Status; + VtdUnitNumber = ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDrhdPostMemory, VtdUnitInfo); + if (VtdUnitNumber == 0) { + return EFI_UNSUPPORTED; } - // - // NOTE: Do not parse RMRR here, because RMRR may cause DMAR programming. - // + for (VTdInfo->VTdEngineCount = 0; VTdInfo->VTdEngineCount < VTD_UNIT_MAX; VTdInfo->VTdEngineCount++) { + if (VtdUnitInfo[VTdInfo->VTdEngineCount].VtdUnitBaseAddress == 0) { + break; + } + } + + VTdInfo->AcpiDmarTable = AcpiDmarTable; return EFI_SUCCESS; } /** - Initializes the Intel VTd DMAR for all memory. + Initializes the Intel VTd DMAR for block all DMA. @retval EFI_SUCCESS Driver is successfully initialized. @retval RETURN_NOT_READY Fail to get VTdInfo Hob . **/ EFI_STATUS -InitVTdDmarForAll ( +InitVTdDmarBlockAll ( VOID ) { - VOID *Hob; - VTD_INFO *VTdInfo; - UINT64 EngineMask; - EFI_STATUS Status; + EFI_ACPI_DMAR_HEADER *AcpiDmarTable; - Hob = GetFirstGuidHob (&mVTdInfoGuid); - if (Hob == NULL) { - DEBUG ((DEBUG_ERROR, "Fail to get VTdInfo Hob.\n")); - return RETURN_NOT_READY; - } - VTdInfo = GET_GUID_HOB_DATA (Hob); - EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1; + // + // Get the DMAR table + // + AcpiDmarTable = GetAcpiDmarTable (); + ASSERT (AcpiDmarTable != NULL); - DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n")); - Status = PrepareVtdConfig (VTdInfo); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - - EnableVTdTranslationProtectionAll (VTdInfo, EngineMask); - - return EFI_SUCCESS; + // + // Parse the DMAR table and block all DMA + // + return ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDhrdPreMemory, NULL); } /** @@ -524,8 +603,8 @@ InitDmaBuffer( DEBUG ((DEBUG_INFO, "InitDmaBuffer :\n")); Hob = GetFirstGuidHob (&mDmaBufferInfoGuid); + ASSERT(Hob != NULL); DmaBufferInfo = GET_GUID_HOB_DATA (Hob); - VtdPmrHobPtr = GetFirstGuidHob (&gVtdPmrInfoDataHobGuid); /** When gVtdPmrInfoDataHobGuid exists, it means: @@ -535,7 +614,7 @@ InitDmaBuffer( 4. Protection regions will be conveyed through VTD_PMR_INFO_HOB When gVtdPmrInfoDataHobGuid dosen't exist, it means: - 1. IntelVTdDmar driver will calcuate the PMR memory alignment + 1. IntelVTdDmarPei driver will calcuate the protected memory alignment 2. Dma buffer is reserved by AllocateAlignedPages() **/ @@ -545,33 +624,40 @@ InitDmaBuffer( return EFI_INVALID_PARAMETER; } - if (VtdPmrHobPtr == NULL) { - // - // Allocate memory for DMA buffer - // - DmaBufferInfo->DmaBufferBase = (UINT64) (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) DmaBufferInfo->DmaBufferSize), 0); - if (DmaBufferInfo->DmaBufferBase == 0) { - DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n")); - return EFI_OUT_OF_RESOURCES; - } - DmaBufferInfo->DmaBufferLimit = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; - DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n")); - } else { - // - // Get the PMR ranges information for the VTd PMR hob - // - VtdPmrHob = GET_GUID_HOB_DATA (VtdPmrHobPtr); - DmaBufferInfo->DmaBufferBase = VtdPmrHob->ProtectedLowLimit; - DmaBufferInfo->DmaBufferLimit = VtdPmrHob->ProtectedHighBase; - } - DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; - DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase; + if (DmaBufferInfo->DmaBufferBase == 0) { + VtdPmrHobPtr = GetFirstGuidHob (&gVtdPmrInfoDataHobGuid); + if (VtdPmrHobPtr != NULL) { + // + // Get the protected memory ranges information from the VTd PMR hob + // + VtdPmrHob = GET_GUID_HOB_DATA (VtdPmrHobPtr); - DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%lx\n", DmaBufferInfo->DmaBufferSize)); - DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%lx\n", DmaBufferInfo->DmaBufferBase)); - DEBUG ((DEBUG_INFO, " DmaBufferLimit : 0x%lx\n", DmaBufferInfo->DmaBufferLimit)); - DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%lx\n", DmaBufferInfo->DmaBufferCurrentTop)); - DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%lx\n", DmaBufferInfo->DmaBufferCurrentBottom)); + if ((VtdPmrHob->ProtectedHighBase - VtdPmrHob->ProtectedLowLimit) < DmaBufferInfo->DmaBufferSize) { + DEBUG ((DEBUG_ERROR, " DmaBufferSize not enough\n")); + return EFI_INVALID_PARAMETER; + } + DmaBufferInfo->DmaBufferBase = VtdPmrHob->ProtectedLowLimit; + } else { + // + // Allocate memory for DMA buffer + // + DmaBufferInfo->DmaBufferBase = (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES (DmaBufferInfo->DmaBufferSize), 0); + if (DmaBufferInfo->DmaBufferBase == 0) { + DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n")); + return EFI_OUT_OF_RESOURCES; + } + DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n")); + } + + DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize; + DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase; + + DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize)); + DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase)); + } + + DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%x\n", DmaBufferInfo->DmaBufferCurrentTop)); + DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%x\n", DmaBufferInfo->DmaBufferCurrentBottom)); return EFI_SUCCESS; } @@ -588,14 +674,14 @@ InitVTdDmarForDma ( VOID ) { - VOID *Hob; VTD_INFO *VTdInfo; + EFI_STATUS Status; EFI_PEI_PPI_DESCRIPTOR *OldDescriptor; EDKII_IOMMU_PPI *OldIoMmuPpi; - Hob = GetFirstGuidHob (&mVTdInfoGuid); - VTdInfo = GET_GUID_HOB_DATA (Hob); + VTdInfo = GetVTdInfoHob (); + ASSERT (VTdInfo != NULL); DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n")); Status = PrepareVtdConfig (VTdInfo); @@ -604,13 +690,6 @@ InitVTdDmarForDma ( return Status; } - DEBUG ((DEBUG_INFO, "PrepareVtdCacheInvalidationConfig\n")); - Status = PrepareVtdCacheInvalidationConfig (VTdInfo); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - // create root entry table DEBUG ((DEBUG_INFO, "SetupTranslationTable\n")); Status = SetupTranslationTable (VTdInfo); @@ -619,10 +698,6 @@ InitVTdDmarForDma ( return Status; } - // If there is RMRR memory, parse it here. - DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n")); - ParseDmarAcpiTableRmrr (VTdInfo); - DEBUG ((DEBUG_INFO, "EnableVtdDmar\n")); Status = EnableVTdTranslationProtection(VTdInfo); if (EFI_ERROR (Status)) { @@ -668,21 +743,10 @@ S3EndOfPeiNotify( IN VOID *Ppi ) { - VOID *Hob; - VTD_INFO *VTdInfo; - UINT64 EngineMask; - DEBUG((DEBUG_INFO, "VTd DMAR PEI S3EndOfPeiNotify\n")); if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) { - Hob = GetFirstGuidHob (&mVTdInfoGuid); - if (Hob == NULL) { - return EFI_SUCCESS; - } - VTdInfo = GET_GUID_HOB_DATA(Hob); - - EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1; - DisableVTdTranslationProtection (VTdInfo, EngineMask); + DisableVTdTranslationProtection (GetVTdInfoHob ()); } return EFI_SUCCESS; } @@ -733,18 +797,13 @@ VTdInfoNotify ( DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized)); - // - // NOTE: We need reinit VTdInfo because previous information might be overriden. - // - InitVTdInfo (); - if (!MemoryInitialized) { // // If the memory is not initialized, // Protect all system memory // - InitVTdDmarForAll (); + InitVTdDmarBlockAll (); // // Install PPI. @@ -758,9 +817,16 @@ VTdInfoNotify ( // Status = InitDmaBuffer (); - ASSERT_EFI_ERROR(Status); + ASSERT_EFI_ERROR (Status); - InitVTdDmarForDma (); + // + // NOTE: We need reinit VTdInfo because previous information might be overriden. + // + Status = InitVTdInfo (); + ASSERT_EFI_ERROR (Status); + + Status = InitVTdDmarForDma (); + ASSERT_EFI_ERROR (Status); } return EFI_SUCCESS; @@ -826,4 +892,3 @@ IntelVTdDmarInitialize ( return EFI_SUCCESS; } - diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h index 7008706030..ce44d6c3cd 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h @@ -9,68 +9,61 @@ #ifndef __DMA_ACCESS_LIB_H__ #define __DMA_ACCESS_LIB_H__ -#define MAX_VTD_PCI_DATA_NUMBER 0x100 - #define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32)) typedef struct { - UINT8 DeviceType; - VTD_SOURCE_ID PciSourceId; -} PEI_PCI_DEVICE_DATA; - -typedef struct { - BOOLEAN IncludeAllFlag; - UINT32 PciDeviceDataNumber; - UINT32 PciDeviceDataMaxNumber; - UINT32 PciDeviceDataPageSize; - UINT32 PciDeviceData; -} PEI_PCI_DEVICE_INFORMATION; - -typedef struct { - UINT32 VtdUnitBaseAddress; + BOOLEAN Done; + UINTN VtdUnitBaseAddress; UINT16 Segment; + UINT8 Flags; VTD_VER_REG VerReg; VTD_CAP_REG CapReg; VTD_ECAP_REG ECapReg; BOOLEAN Is5LevelPaging; - UINT32 FixedSecondLevelPagingEntry; - UINT32 RmrrSecondLevelPagingEntry; - UINT32 RootEntryTable; - UINT32 ExtRootEntryTable; - UINT16 RootEntryTablePageSize; - UINT16 ExtRootEntryTablePageSize; - PEI_PCI_DEVICE_INFORMATION PciDeviceInfo; UINT8 EnableQueuedInvalidation; - UINT16 QiDescLength; + UINT16 QueueSize; QI_DESC *QiDesc; UINT16 QiFreeHead; + UINTN FixedSecondLevelPagingEntry; + UINTN RootEntryTable; + UINTN ExtRootEntryTable; + UINTN RootEntryTablePageSize; + UINTN ExtRootEntryTablePageSize; } VTD_UNIT_INFO; typedef struct { - UINT32 AcpiDmarTable; + EFI_ACPI_DMAR_HEADER *AcpiDmarTable; UINT8 HostAddressWidth; - UINT32 VTdEngineCount; - VTD_UNIT_INFO VtdUnitInfo[1]; + UINTN VTdEngineCount; + VTD_UNIT_INFO *VtdUnitInfo; } VTD_INFO; typedef struct { - UINT64 DmaBufferBase; - UINT64 DmaBufferSize; - UINT64 DmaBufferLimit; - UINT64 DmaBufferCurrentTop; - UINT64 DmaBufferCurrentBottom; + UINTN DmaBufferBase; + UINTN DmaBufferSize; + UINTN DmaBufferCurrentTop; + UINTN DmaBufferCurrentBottom; } DMA_BUFFER_INFO; -/** - Enable VTd translation table protection. - - @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. -**/ +typedef VOID -EnableVTdTranslationProtectionAll ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask +(*PROCESS_DRHD_CALLBACK_FUNC) ( + IN OUT VOID *Context, + IN UINT32 VTdIndex, + IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd + ); + +/** + Enable VTd translation table protection for block DMA + + @param[in] VtdUnitBaseAddress The base address of the VTd engine. + + @retval EFI_SUCCESS DMAR translation is enabled. + @retval EFI_DEVICE_ERROR DMAR translation is not enabled. +**/ +EFI_STATUS +EnableVTdTranslationProtectionBlockDma ( + IN UINTN VtdUnitBaseAddress ); /** @@ -90,34 +83,27 @@ EnableVTdTranslationProtection ( Disable VTd translation table protection. @param[in] VTdInfo The VTd engine context information. - @param[in] EngineMask The mask of the VTd engine to be accessed. **/ VOID DisableVTdTranslationProtection ( - IN VTD_INFO *VTdInfo, - IN UINT64 EngineMask + IN VTD_INFO *VTdInfo ); /** Parse DMAR DRHD table. @param[in] AcpiDmarTable DMAR ACPI table + @param[in] Callback Callback function for handle DRHD + @param[in] Context Callback function Context + + @return the VTd engine number. - @return EFI_SUCCESS The DMAR DRHD table is parsed. **/ -EFI_STATUS +UINTN ParseDmarAcpiTableDrhd ( - IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable - ); - -/** - Parse DMAR DRHD table. - - @param[in] VTdInfo The VTd engine context information. -**/ -VOID -ParseDmarAcpiTableRmrr ( - IN VTD_INFO *VTdInfo + IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable, + IN PROCESS_DRHD_CALLBACK_FUNC Callback, + IN VOID *Context ); /** @@ -214,30 +200,7 @@ GetPciDataIndex ( IN VTD_SOURCE_ID SourceId ); -/** - Always enable the VTd page attribute for the device. - - @param[in] VTdInfo The VTd engine context information. - @param[in] Segment The Segment used to identify a VTd engine. - @param[in] SourceId The SourceId used to identify a VTd engine and table entry. - @param[in] MemoryBase The base of the memory. - @param[in] MemoryLimit The limit of the memory. - @param[in] IoMmuAccess The IOMMU access. - - @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device. -**/ -EFI_STATUS -EnableRmrrPageAttribute ( - IN VTD_INFO *VTdInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId, - IN UINT64 MemoryBase, - IN UINT64 MemoryLimit, - IN UINT64 IoMmuAccess - ); - extern EFI_GUID mVTdInfoGuid; extern EFI_GUID mDmaBufferInfoGuid; #endif - diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c index bd54986701..221bafbb61 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c @@ -1,6 +1,7 @@ /** @file Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -129,12 +130,12 @@ CreateSecondLevelPagingEntryTable ( FlushPageTableMemory (VTdUnitInfo, (UINTN) SecondLevelPagingEntry, EFI_PAGES_TO_SIZE (1)); } - DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", SecondLevelPagingEntry)); + DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry)); // // If no access is needed, just create not present entry. // if (IoMmuAccess == 0) { - DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN) SecondLevelPagingEntry)); + DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx Access 0\n", (UINT64) (UINTN) SecondLevelPagingEntry)); return SecondLevelPagingEntry; } @@ -244,7 +245,7 @@ CreateSecondLevelPagingEntryTable ( } FlushPageTableMemory (VTdUnitInfo, (UINTN) &Lvl5PtEntry[Lvl5Start], (UINTN) &Lvl5PtEntry[Lvl5End + 1] - (UINTN) &Lvl5PtEntry[Lvl5Start]); - DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN)SecondLevelPagingEntry)); + DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry)); return SecondLevelPagingEntry; } @@ -276,6 +277,10 @@ CreateContextEntry ( VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry; UINT64 Pt; + if (VTdUnitInfo->RootEntryTable != 0) { + return EFI_SUCCESS; + } + RootPages = EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTRY_NUMBER); ContextPages = EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CONTEXT_ENTRY_NUMBER); EntryTablePages = RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER); @@ -286,8 +291,8 @@ CreateContextEntry ( } DEBUG ((DEBUG_ERROR, "RootEntryTable address - 0x%x\n", Buffer)); - VTdUnitInfo->RootEntryTable = (UINT32) (UINTN) Buffer; - VTdUnitInfo->RootEntryTablePageSize = (UINT16) EntryTablePages; + VTdUnitInfo->RootEntryTable = (UINTN) Buffer; + VTdUnitInfo->RootEntryTablePageSize = EntryTablePages; RootEntryBase = (VTD_ROOT_ENTRY *) Buffer; Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages); @@ -304,7 +309,7 @@ CreateContextEntry ( RootEntry->Bits.ContextTablePointerHi = (UINT32) RShiftU64 ((UINT64) (UINTN) Buffer, 32); RootEntry->Bits.Present = 1; Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages); - ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ; + ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi); for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) { SourceId.Index.ContextIndex = (UINT8) ContextIndex; @@ -317,7 +322,7 @@ CreateContextEntry ( ContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2; if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) { - SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry; + SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry; Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12); ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20); @@ -359,6 +364,10 @@ CreateExtContextEntry ( VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry; UINT64 Pt; + if (VTdUnitInfo->ExtRootEntryTable != 0) { + return EFI_SUCCESS; + } + RootPages = EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_ENTRY_NUMBER); ContextPages = EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD_CONTEXT_ENTRY_NUMBER); EntryTablePages = RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER); @@ -369,8 +378,8 @@ CreateExtContextEntry ( } DEBUG ((DEBUG_ERROR, "ExtRootEntryTable address - 0x%x\n", Buffer)); - VTdUnitInfo->ExtRootEntryTable = (UINT32) (UINTN) Buffer; - VTdUnitInfo->ExtRootEntryTablePageSize = (UINT16) EntryTablePages; + VTdUnitInfo->ExtRootEntryTable = (UINTN) Buffer; + VTdUnitInfo->ExtRootEntryTablePageSize = EntryTablePages; ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) Buffer; Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages); @@ -390,7 +399,7 @@ CreateExtContextEntry ( ExtRootEntry->Bits.UpperContextTablePointerHi = (UINT32) RShiftU64 (RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20); ExtRootEntry->Bits.UpperPresent = 1; Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages); - ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ; + ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi); for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) { SourceId.Index.ContextIndex = (UINT8) ContextIndex; @@ -403,7 +412,7 @@ CreateExtContextEntry ( ExtContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2; if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) { - SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry; + SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry; Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12); ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; @@ -791,9 +800,6 @@ SetSecondLevelPagingAttribute ( SplitAttribute = NeedSplitPage (BaseAddress, Length, PageAttribute); if (SplitAttribute == PageNone) { ConvertSecondLevelPageEntryAttribute (VTdUnitInfo, PageEntry, IoMmuAccess, &IsEntryModified); - if (IsEntryModified) { - //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE; - } // // Convert success, move to next // @@ -805,7 +811,6 @@ SetSecondLevelPagingAttribute ( DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status)); return RETURN_UNSUPPORTED; } - //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE; // // Just split current page // Convert success in next around @@ -837,7 +842,11 @@ CreateFixedSecondLevelPagingEntry ( VOID *Hob; DMA_BUFFER_INFO *DmaBufferInfo; - VTdUnitInfo->FixedSecondLevelPagingEntry = (UINT32) (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0); + if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) { + return EFI_SUCCESS; + } + + VTdUnitInfo->FixedSecondLevelPagingEntry = (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0); if (VTdUnitInfo->FixedSecondLevelPagingEntry == 0) { DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n")); return EFI_OUT_OF_RESOURCES; @@ -846,14 +855,14 @@ CreateFixedSecondLevelPagingEntry ( Hob = GetFirstGuidHob (&mDmaBufferInfoGuid); DmaBufferInfo = GET_GUID_HOB_DATA (Hob); BaseAddress = DmaBufferInfo->DmaBufferBase; - Length = DmaBufferInfo->DmaBufferLimit - DmaBufferInfo->DmaBufferBase; + Length = DmaBufferInfo->DmaBufferSize; IoMmuAccess = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE; DEBUG ((DEBUG_INFO, " BaseAddress = 0x%lx\n", BaseAddress)); DEBUG ((DEBUG_INFO, " Length = 0x%lx\n", Length)); DEBUG ((DEBUG_INFO, " IoMmuAccess = 0x%lx\n", IoMmuAccess)); - Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess); + Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess); return Status; } @@ -877,6 +886,9 @@ SetupTranslationTable ( for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) { VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index]; + if (VtdUnitInfo->Done) { + continue; + } Status = CreateFixedSecondLevelPagingEntry (VtdUnitInfo); if (EFI_ERROR (Status)) { @@ -911,151 +923,3 @@ SetupTranslationTable ( return EFI_SUCCESS; } -/** - Find the VTd index by the Segment and SourceId. - - @param[in] VTdInfo The VTd engine context information. - @param[in] Segment The segment of the source. - @param[in] SourceId The SourceId of the source. - @param[out] ExtContextEntry The ExtContextEntry of the source. - @param[out] ContextEntry The ContextEntry of the source. - - @return The index of the VTd engine. - @retval (UINTN)-1 The VTd engine is not found. -**/ -UINTN -FindVtdIndexBySegmentSourceId ( - IN VTD_INFO *VTdInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId, - OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry, - OUT VTD_CONTEXT_ENTRY **ContextEntry - ) -{ - UINTN VtdIndex; - VTD_ROOT_ENTRY *RootEntryBase; - VTD_ROOT_ENTRY *RootEntry; - VTD_CONTEXT_ENTRY *ContextEntryTable; - VTD_CONTEXT_ENTRY *ThisContextEntry; - VTD_EXT_ROOT_ENTRY *ExtRootEntryBase; - VTD_EXT_ROOT_ENTRY *ExtRootEntry; - VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable; - VTD_EXT_CONTEXT_ENTRY *ThisExtContextEntry; - - for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) { - if (GetPciDataIndex (&VTdInfo->VtdUnitInfo[VtdIndex], Segment, SourceId) != (UINTN)-1) { - DEBUG ((DEBUG_INFO, "Find VtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - break; - } - } - if (VtdIndex >= VTdInfo->VTdEngineCount) { - for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) { - if (Segment != VTdInfo->VtdUnitInfo[VtdIndex].Segment) { - continue; - } - if (VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.IncludeAllFlag) { - DEBUG ((DEBUG_INFO, "Find IncludeAllFlag VtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - break; - } - } - } - - if (VtdIndex < VTdInfo->VTdEngineCount) { - ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable; - if (ExtRootEntryBase != 0) { - ExtRootEntry = &ExtRootEntryBase[SourceId.Index.RootIndex]; - ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ; - ThisExtContextEntry = &ExtContextEntryTable[SourceId.Index.ContextIndex]; - if (ThisExtContextEntry->Bits.AddressWidth == 0) { - DEBUG ((DEBUG_INFO, "ExtContextEntry AddressWidth : 0x%x\n", ThisExtContextEntry->Bits.AddressWidth)); - return (UINTN)-1; - } - *ExtContextEntry = ThisExtContextEntry; - *ContextEntry = NULL; - } else { - RootEntryBase = (VTD_ROOT_ENTRY*) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable; - RootEntry = &RootEntryBase[SourceId.Index.RootIndex]; - ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ; - ThisContextEntry = &ContextEntryTable[SourceId.Index.ContextIndex]; - if (ThisContextEntry->Bits.AddressWidth == 0) { - DEBUG ((DEBUG_INFO, "ContextEntry AddressWidth : 0x%x\n", ThisContextEntry->Bits.AddressWidth)); - return (UINTN)-1; - } - *ExtContextEntry = NULL; - *ContextEntry = ThisContextEntry; - } - - return VtdIndex; - } - - return (UINTN)-1; -} - -/** - Always enable the VTd page attribute for the device. - - @param[in] VTdInfo The VTd engine context information. - @param[in] Segment The Segment used to identify a VTd engine. - @param[in] SourceId The SourceId used to identify a VTd engine and table entry. - @param[in] MemoryBase The base of the memory. - @param[in] MemoryLimit The limit of the memory. - @param[in] IoMmuAccess The IOMMU access. - - @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device. -**/ -EFI_STATUS -EnableRmrrPageAttribute ( - IN VTD_INFO *VTdInfo, - IN UINT16 Segment, - IN VTD_SOURCE_ID SourceId, - IN UINT64 MemoryBase, - IN UINT64 MemoryLimit, - IN UINT64 IoMmuAccess - ) -{ - EFI_STATUS Status; - UINTN VtdIndex; - VTD_EXT_CONTEXT_ENTRY *ExtContextEntry; - VTD_CONTEXT_ENTRY *ContextEntry; - VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry; - UINT64 Pt; - - DEBUG ((DEBUG_INFO, "EnableRmrrPageAttribute (S%04x B%02x D%02x F%02x)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - - VtdIndex = FindVtdIndexBySegmentSourceId (VTdInfo, Segment, SourceId, &ExtContextEntry, &ContextEntry); - if (VtdIndex == (UINTN)-1) { - DEBUG ((DEBUG_ERROR, "EnableRmrrPageAttribute - Can not locate Pci device (S%04x B%02x D%02x F%02x) !\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)); - return EFI_DEVICE_ERROR; - } - - if (VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry == 0) { - DEBUG ((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex)); - VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry = (UINT32)(UINTN)CreateSecondLevelPagingEntryTable (&VTdInfo->VtdUnitInfo[VtdIndex], NULL, 0, SIZE_4GB, 0); - if (VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry == 0) { - return EFI_OUT_OF_RESOURCES; - } - - Status =SetSecondLevelPagingAttribute (&VTdInfo->VtdUnitInfo[VtdIndex], (VTD_SECOND_LEVEL_PAGING_ENTRY*)(UINTN)VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry, MemoryBase, MemoryLimit + 1 - MemoryBase, IoMmuAccess); - if (EFI_ERROR (Status)) { - return Status; - } - } - - SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry; - Pt = (UINT64) RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12); - if (ExtContextEntry != NULL) { - ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; - ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20); - ExtContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1); - ExtContextEntry->Bits.Present = 1; - FlushPageTableMemory (&VTdInfo->VtdUnitInfo[VtdIndex], (UINTN) ExtContextEntry, sizeof(*ExtContextEntry)); - } else if (ContextEntry != NULL) { - ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt; - ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64 (Pt, 20); - ContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1); - ContextEntry->Bits.Present = 1; - FlushPageTableMemory (&VTdInfo->VtdUnitInfo[VtdIndex], (UINTN) ContextEntry, sizeof (*ContextEntry)); - } - - return EFI_SUCCESS; -} From 4a5c401e0edb5b48c9b47cd38c0503cd8fb0f431 Mon Sep 17 00:00:00 2001 From: "Sheng, W" Date: Tue, 8 Feb 2022 10:03:11 +0800 Subject: [PATCH 19/26] IntelSiliconPkg/VTd: Use Legacy Mode Address Translation Only if ECAP_REG.SMTS == 0 and ECAP_REG.bit 24 == 1, use extended mode address translation. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3826 Reviewed-by: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Cc: Robert Kowalewski Signed-off-by: Sheng Wei --- IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c | 2 +- IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 2 +- IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c index 41db207367..b04d6e9c17 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c @@ -626,7 +626,7 @@ EnableVTdTranslationProtection ( if (VtdUnitInfo->ExtRootEntryTable != 0) { DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", Index, VtdUnitInfo->ExtRootEntryTable)); - Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable); + Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable | BIT11); } else { DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", Index, VtdUnitInfo->RootEntryTable)); Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->RootEntryTable); diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c index 221bafbb61..c6fe86daa1 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c @@ -902,7 +902,7 @@ SetupTranslationTable ( ASSERT(FALSE); Status = EFI_UNSUPPORTED; } else { - Status = CreateExtContextEntry (VtdUnitInfo); + Status = CreateContextEntry (VtdUnitInfo); } } else { if (VtdUnitInfo->ECapReg.Bits.DEP_24) { diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c index 67428ec545..ea7e48a4c5 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c @@ -389,7 +389,7 @@ SetupTranslationTable ( ASSERT(FALSE); Status = EFI_UNSUPPORTED; } else { - Status = CreateExtContextEntry (Index); + Status = CreateContextEntry (Index); } } else { if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) { From db7fcc290618af9985fa414285be0a9555fc8981 Mon Sep 17 00:00:00 2001 From: Maciej Czajkowski Date: Tue, 7 Dec 2021 23:20:32 +0800 Subject: [PATCH 20/26] IntelSiliconPkg: Add IntelDieInfoProtocol Added IntelDieInfo header into IntelSiliconPkg tree. The purpose is to have generic and unified interface for getting information about dies installed in the system. It will be implemented by silicon code. Reviewed-by: Ray Ni Reviewed-by: Rangasai V Chaganty Signed-off-by: Maciej Czajkowski --- .../Include/Protocol/IntelDieInfo.h | 94 +++++++++++++++++++ IntelSiliconPkg/IntelSiliconPkg.dec | 9 ++ 2 files changed, 103 insertions(+) create mode 100644 IntelSiliconPkg/Include/Protocol/IntelDieInfo.h diff --git a/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h b/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h new file mode 100644 index 0000000000..82e48220fd --- /dev/null +++ b/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h @@ -0,0 +1,94 @@ +/** @file + IntelDieInfo definition + + Copyright (c) 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef _DIE_INFO_PROTOCOL_H_ +#define _DIE_INFO_PROTOCOL_H_ + +typedef struct _EDKII_INTEL_DIE_INFO_PROTOCOL EDKII_INTEL_DIE_INFO_PROTOCOL; +typedef EDKII_INTEL_DIE_INFO_PROTOCOL EDKII_INTEL_DIE_INFO_PPI; + +extern EFI_GUID gIntelDieInfoProtocolGuid; +extern EFI_GUID gIntelDieInfoPpiGuid; + +extern EFI_GUID gIntelDieInfoPchGuid; +extern EFI_GUID gIntelDieInfoSocGuid; +extern EFI_GUID gIntelDieInfoIoGuid; +extern EFI_GUID gIntelDieInfoCpuGuid; +extern EFI_GUID gIntelDieInfoGfxGuid; + +#define DIE_INFO_PROTOCOL_REVISION 1 + +/** + Returns pointer to constant string representing die name. + Name is specific to die type. + + @param[in] This Pointer to the DieInfoProtocol context structure + @retval Pointer to the const string +**/ +typedef +CONST CHAR8* +(EFIAPI *EDKII_INTEL_DIE_INFO_GET_DIE_NAME_STR) ( + IN EDKII_INTEL_DIE_INFO_PROTOCOL *This + ); + +/** + Returns pointer to constant string representing stepping of the die. + + @param[in] This Pointer to the DieInfoProtocol context structure + @retval Pointer to the const string +**/ +typedef +CONST CHAR8* +(EFIAPI *EDKII_INTEL_DIE_INFO_GET_STEPPING_STR) ( + IN EDKII_INTEL_DIE_INFO_PROTOCOL *This + ); + +/** + Returns pointer to constant string representing SKU of the die. + + @param[in] This Pointer to the DieInfoProtocol context structure + @retval Pointer to the const string +**/ +typedef +CONST CHAR8* +(EFIAPI *EDKII_INTEL_DIE_INFO_GET_SKU_STR) ( + IN EDKII_INTEL_DIE_INFO_PROTOCOL *This + ); + +/** + Protocol/PPI definition. + The purpose of this interface is to serve die-specific informations in a unified, generic way. + It will be produced by silicon code per die, and can be consumed by any module that needs contained information. + + Revision 1: + - Initial version. +**/ +struct _EDKII_INTEL_DIE_INFO_PROTOCOL { + UINT32 Revision; ///< Current protocol revision + /** + Type of the die that particular instance is reffering to. + **/ + EFI_GUID Type; + /** + Index of the die in the package. + **/ + UINT32 DieIndex; + /** + Unique ID specific to the die and the associated generation. + **/ + UINT64 DieId; + /** + Generation and die specific stepping ID. + **/ + UINT32 SteppingId; + + EDKII_INTEL_DIE_INFO_GET_DIE_NAME_STR GetNameStr; + EDKII_INTEL_DIE_INFO_GET_STEPPING_STR GetSteppingStr; + EDKII_INTEL_DIE_INFO_GET_SKU_STR GetSkuStr; +}; + +#endif // _DIE_INFO_PROTOCOL_H_ diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index e482410bee..181e91c431 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -92,12 +92,20 @@ gFlashRegionAllGuid = { 0xbabe60dc, 0xf88d, 0x4584, {0x9e, 0x54, 0x57, 0x44, 0x4b, 0xe2, 0x6e, 0xf3 } } gFlashRegionMaxGuid = { 0x74c2e3c1, 0x8faa, 0x4659, {0xa7, 0xbb, 0x87, 0x1f, 0xbb, 0x61, 0xd3, 0xb4 } } + ## Include/Protocol/IntelDieInfo.h + gIntelDieInfoPchGuid = { 0x62CB6D68, 0x4771, 0x4569, { 0x81, 0xFA, 0x1E, 0x99, 0x6E, 0xA9, 0x91, 0xC5 }} + gIntelDieInfoSocGuid = { 0x63287105, 0x578E, 0x4799, { 0xBE, 0x55, 0x5D, 0xDA, 0xCA, 0x03, 0x74, 0xD0 }} + gIntelDieInfoIoGuid = { 0x23DA4C74, 0x54A0, 0x4E01, { 0x83, 0xB1, 0x8C, 0xA7, 0x43, 0x43, 0x1F, 0xF0 }} + gIntelDieInfoCpuGuid = { 0x6E5AF2E3, 0x5D84, 0x48F2, { 0x84, 0x28, 0x99, 0xE4, 0x93, 0x4F, 0x51, 0xE4 }} + gIntelDieInfoGfxGuid = { 0x1D3D2599, 0x7A1C, 0x4B1E, { 0x8C, 0xC5, 0x0F, 0x88, 0x27, 0xA0, 0x2E, 0xEC }} + [Ppis] ## Include/Ppi/Spi2.h gPchSpi2PpiGuid = { 0x63c40580, 0x10c4, 0x4a8e, { 0xb4, 0x16, 0x86, 0x85, 0x25, 0x7e, 0xce, 0x04 } } gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } } gEdkiiVTdNullRootEntryTableGuid = { 0x3de0593f, 0x6e3e, 0x4542, { 0xa1, 0xcb, 0xcb, 0xb2, 0xdb, 0xeb, 0xd8, 0xff } } + gIntelDieInfoPpiGuid = { 0xF9E45CBF, 0x1E21, 0x434A, { 0x90, 0x88, 0x1D, 0x10, 0x38, 0xF3, 0x68, 0xF2 }} [Protocols] ## Protocols that provide services for the Intel(R) PCH SPI Host Controller Compatibility Interface @@ -107,6 +115,7 @@ gPchSmmSpi2ProtocolGuid = { 0x2d1c0c43, 0x20d3, 0x40ae, { 0x99, 0x07, 0x2d, 0xf0, 0xe7, 0x91, 0x21, 0xa5 } } gEdkiiPlatformVTdPolicyProtocolGuid = { 0x3d17e448, 0x466, 0x4e20, { 0x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }} + gIntelDieInfoProtocolGuid = { 0xAED8A0A1, 0xFDE6, 0x4CF2, { 0xA3, 0x85, 0x08, 0xF1, 0x25, 0xF2, 0x40, 0x37 }} ## Protocol for device security policy. # Include/Protocol/PlatformDeviceSecurityPolicy.h From 18937fe65138529aa4f9a8ff52ef686403da4e3e Mon Sep 17 00:00:00 2001 From: Ted Kuo Date: Tue, 15 Feb 2022 10:31:22 +0800 Subject: [PATCH 21/26] IntelSiliconPkg/VTd: Fix to support IntelVTdDmarPei in 64bit REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3836 Changed VtdIndex defined in PROCESS_DRHD_CALLBACK_FUNC from UINT32 to UINTN to avoid type incompatible error when enable PEI in 64bit. Cc: Sheng Wei Reviewed-by: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Reviewed-by: Robert Kowalewski Reviewed-by: Sheng Wei Signed-off-by: Ted Kuo --- IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c | 4 ++-- IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c index c883d398cc..0a0dc22a23 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c @@ -434,7 +434,7 @@ GetVTdInfoHob ( VOID ProcessDhrdPreMemory ( IN OUT VOID *Context, - IN UINT32 VTdIndex, + IN UINTN VTdIndex, IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd ) { @@ -454,7 +454,7 @@ ProcessDhrdPreMemory ( VOID ProcessDrhdPostMemory ( IN OUT VOID *Context, - IN UINT32 VTdIndex, + IN UINTN VTdIndex, IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd ) { diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h index ce44d6c3cd..72f00710d0 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h @@ -49,7 +49,7 @@ typedef VOID (*PROCESS_DRHD_CALLBACK_FUNC) ( IN OUT VOID *Context, - IN UINT32 VTdIndex, + IN UINTN VTdIndex, IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd ); From 496b12f0955454f2fd45b1bb1d5e597bc156ef91 Mon Sep 17 00:00:00 2001 From: Sheng Wei Date: Tue, 10 May 2022 16:25:45 +0800 Subject: [PATCH 22/26] IntelSiliconPkg/VTd: Add PCD for VTd Abort DMA Mode Support PcdVTdSupportAbortDmaMode is used to enable/disable using VTd Abort DMA Mode. Signed-off-by: Sheng Wei Reviewed-by: Jenny Huang Reviewed-by: Robert Kowalewski Cc: Ray Ni Cc: Rangasai V Chaganty Change-Id: If999d2f4906bda887dffe8574ec17cb90346b710 --- .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c | 11 +++++++---- .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.inf | 3 ++- IntelSiliconPkg/IntelSiliconPkg.dec | 6 ++++++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c index b04d6e9c17..4b6dbe96bf 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c @@ -1,6 +1,6 @@ /** @file - Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.
+ Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -570,10 +570,12 @@ EnableVTdTranslationProtectionBlockDma ( DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n", VtdUnitBaseAddress)); - ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG); - DEBUG ((DEBUG_INFO, "ECapReg : 0%016lx\n", ECapReg.Uint64)); + DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", FixedPcdGetBool (PcdVTdSupportAbortDmaMode))); - if (ECapReg.Bits.ADMS == 1) { + ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG); + DEBUG ((DEBUG_INFO, "ECapReg.ADMS : %d\n", ECapReg.Bits.ADMS)); + + if ((ECapReg.Bits.ADMS == 1) && FixedPcdGetBool (PcdVTdSupportAbortDmaMode)) { // // Use Abort DMA Mode // @@ -594,6 +596,7 @@ EnableVTdTranslationProtectionBlockDma ( ASSERT (FALSE); return EFI_DEVICE_ERROR; } + DEBUG ((DEBUG_INFO, "Block All DMA by TE.\n")); Status = EnableDmarPreMem (VtdUnitBaseAddress, (UINT64) (*RootEntryTable)); } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.inf b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.inf index f448dc8524..a0fbea43bd 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.inf +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.inf @@ -4,7 +4,7 @@ # This driver initializes VTd engine based upon EDKII_VTD_INFO_PPI # and provide DMA protection in PEI. # -# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# Copyright (c) 2022, Intel Corporation. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -55,6 +55,7 @@ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSize ## CONSUMES gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3 ## CONSUMES + gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode ## CONSUMES [Depex] gEfiPeiMasterBootModePpiGuid AND diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec index 181e91c431..84e90b858b 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/IntelSiliconPkg/IntelSiliconPkg.dec @@ -135,6 +135,12 @@ gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize|0x000A0000|UINT32|0x0000000A gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvOffset|0x00660000|UINT32|0x0000000B + ## Indicates if VTd Abort DMA Mode is supported.

+ # TRUE - Support VTd abort DMA mode. + # FALSE - Not support VTd abort DMA mode. + # @Prompt VTd abort DMA mode support. + gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOOLEAN|0x0000000C + [PcdsFixedAtBuild, PcdsPatchableInModule] ## Error code for VTd error.

# EDKII_ERROR_CODE_VTD_ERROR = (EFI_IO_BUS_UNSPECIFIED | (EFI_OEM_SPECIFIC | 0x00000000)) = 0x02008000
From b7bd9c41f6e406594fc18f90a239eb21ebab2c52 Mon Sep 17 00:00:00 2001 From: Sheng Wei Date: Mon, 27 Jun 2022 14:58:01 +0800 Subject: [PATCH 23/26] IntelSiliconPkg/VTd: Fix VTd Queued Invalidation IOTLB descriptor VTd Queued Invalidation IOTLB descriptor need to use CAP_REG.DWD and CAP_REG.DRD. Queued Invalidation descriptor is a 128 bits value. Register-based invalidation interface supported by hardware implementations of this architecture with Major Version 5 or lower (VER_REG). REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3964 Signed-off-by: Sheng Wei Reviewed-by: Jenny Huang Cc: Ray Ni Cc: Rangasai V Chaganty --- .../VTd/IntelVTdDmarPei/IntelVTdDmar.c | 32 +++++++++---------- .../VTd/IntelVTdDmarPei/IntelVTdDmarPei.h | 2 +- .../Feature/VTd/IntelVTdDxe/VtdReg.c | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c index 4b6dbe96bf..f9a06619d7 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c @@ -79,7 +79,7 @@ PerpareCacheInvalidationInterface ( IN VTD_UNIT_INFO *VTdUnitInfo ) { - UINT16 QiDescLength; + UINT16 QueueSize; UINT64 Reg64; UINT32 Reg32; VTD_ECAP_REG ECapReg; @@ -122,18 +122,18 @@ PerpareCacheInvalidationInterface ( // Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register // if (VTdUnitInfo->QiDesc == NULL) { - VTdUnitInfo->QueueSize = 0; - QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); - VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength)); + QueueSize = 0; + VTdUnitInfo->QiDescLength = 1 << (QueueSize + 8); + VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES (sizeof (QI_DESC) * VTdUnitInfo->QiDescLength)); if (VTdUnitInfo->QiDesc == NULL) { DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n")); return EFI_OUT_OF_RESOURCES; } } - DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", QiDescLength)); + DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", VTdUnitInfo->QiDescLength)); Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc; - Reg64 |= VTdUnitInfo->QueueSize; + Reg64 |= QueueSize; MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64); // @@ -164,7 +164,6 @@ DisableQueuedInvalidationInterface ( ) { UINT32 Reg32; - UINT16 QiDescLength; if (VTdUnitInfo->EnableQueuedInvalidation != 0) { Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG); @@ -176,10 +175,9 @@ DisableQueuedInvalidationInterface ( } while ((Reg32 & B_GSTS_REG_QIES) != 0); if (VTdUnitInfo->QiDesc != NULL) { - QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); - FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength)); + FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES (sizeof (QI_DESC) * VTdUnitInfo->QiDescLength)); VTdUnitInfo->QiDesc = NULL; - VTdUnitInfo->QueueSize = 0; + VTdUnitInfo->QiDescLength = 0; } VTdUnitInfo->EnableQueuedInvalidation = 0; @@ -239,10 +237,10 @@ SubmitQueuedInvalidationDescriptor ( return EFI_INVALID_PARAMETER; } - QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8); + QiDescLength = VTdUnitInfo->QiDescLength; BaseDesc = VTdUnitInfo->QiDesc; - DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%08x, 0x%08x]\n", VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High)); + DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%016lx, 0x%016lx]\n", VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High)); BaseDesc[VTdUnitInfo->QiFreeHead].Low = Desc->Low; BaseDesc[VTdUnitInfo->QiFreeHead].High = Desc->High; @@ -251,7 +249,6 @@ SubmitQueuedInvalidationDescriptor ( DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead)); VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) % QiDescLength; - Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG); // // Update the HW tail register indicating the presence of new descriptors. // @@ -328,6 +325,7 @@ InvalidateIOTLB ( { UINT64 Reg64; VTD_ECAP_REG ECapReg; + VTD_CAP_REG CapReg; QI_DESC QiDesc; if (VTdUnitInfo->EnableQueuedInvalidation == 0) { @@ -353,8 +351,8 @@ InvalidateIOTLB ( // // Queued Invalidation // - ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG); - QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(ECapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(ECapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE; + CapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CAP_REG); + QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE; QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0); return SubmitQueuedInvalidationDescriptor(VTdUnitInfo, &QiDesc); @@ -364,7 +362,7 @@ InvalidateIOTLB ( } /** - Enable DMAR translation inpre-mem phase. + Enable DMAR translation in pre-mem phase. @param[in] VtdUnitBaseAddress The base address of the VTd engine. @param[in] RtaddrRegValue The value of RTADDR_REG. @@ -400,7 +398,7 @@ EnableDmarPreMem ( Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG); // - // Write Buffer Flush before invalidation + // Write Buffer Flush // FlushWriteBuffer (VtdUnitBaseAddress); diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h index 72f00710d0..fad57f5ced 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h @@ -21,7 +21,7 @@ typedef struct { VTD_ECAP_REG ECapReg; BOOLEAN Is5LevelPaging; UINT8 EnableQueuedInvalidation; - UINT16 QueueSize; + UINT16 QiDescLength; QI_DESC *QiDesc; UINT16 QiFreeHead; UINTN FixedSecondLevelPagingEntry; diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c index 0e405cf19b..a193d6bba4 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c @@ -72,7 +72,7 @@ PerpareCacheInvalidationInterface ( UINT64 Reg64; UINT32 Reg32; - if (mVtdUnitInformation[VtdIndex].VerReg.Bits.Major <= 6) { + if (mVtdUnitInformation[VtdIndex].VerReg.Bits.Major <= 5) { mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation = 0; DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [%d]\n", VtdIndex)); return EFI_SUCCESS; From 81e0246c615502456b4c76e020f2c7f0c672dcff Mon Sep 17 00:00:00 2001 From: Michael Kubacki Date: Fri, 1 Jul 2022 07:39:43 -0700 Subject: [PATCH 24/26] IntelSiliconPkg/SpiFvbService: Add support for VariableFlashInfoLib REF:https://bugzilla.tianocore.org/show_bug.cgi?id=3478 Adds support for getting the variable flash information from VariableFlashInfoLib. This library abstracts the source of flash information so platforms could expect the information to come from a different source in the library implementation than the PCDs previously used as the information source in this module. In particular, the library allows Standalone MM platforms to dynamically pass the information behind the library API. Cc: Rangasai V Chaganty Cc: Ray Ni Cc: Isaac Oram Cc: Nate DeSimone Signed-off-by: Michael Kubacki Reviewed-by: Sai Chaganty Reviewed-by: Isaac Oram --- .../Feature/Flash/SpiFvbService/FvbInfo.c | 128 ++++++++++++------ .../Flash/SpiFvbService/SpiFvbServiceCommon.c | 93 ++++++++++++- .../Flash/SpiFvbService/SpiFvbServiceCommon.h | 18 ++- .../Flash/SpiFvbService/SpiFvbServiceMm.c | 49 ++++++- .../Flash/SpiFvbService/SpiFvbServiceSmm.inf | 6 +- .../SpiFvbServiceStandaloneMm.inf | 6 +- IntelSiliconPkg/IntelSiliconPkg.dsc | 7 + 7 files changed, 243 insertions(+), 64 deletions(-) diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c index 88320e6790..e3720bbb34 100644 --- a/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c @@ -3,6 +3,7 @@ These data is intent to decouple FVB driver with FV header. Copyright (c) 2017, Intel Corporation. All rights reserved.
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -11,51 +12,92 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #define FIRMWARE_BLOCK_SIZE 0x10000 #define FVB_MEDIA_BLOCK_SIZE FIRMWARE_BLOCK_SIZE - -#define NV_STORAGE_BASE_ADDRESS FixedPcdGet32(PcdFlashNvStorageVariableBase) -#define SYSTEM_NV_BLOCK_NUM ((FixedPcdGet32(PcdFlashNvStorageVariableSize)+ FixedPcdGet32(PcdFlashNvStorageFtwWorkingSize) + FixedPcdGet32(PcdFlashNvStorageFtwSpareSize))/ FVB_MEDIA_BLOCK_SIZE) - typedef struct { EFI_PHYSICAL_ADDRESS BaseAddress; EFI_FIRMWARE_VOLUME_HEADER FvbInfo; EFI_FV_BLOCK_MAP_ENTRY End[1]; } EFI_FVB2_MEDIA_INFO; -// -// This data structure contains a template of all correct FV headers, which is used to restore -// Fv header if it's corrupted. -// -EFI_FVB2_MEDIA_INFO mPlatformFvbMediaInfo[] = { - // - // Systen NvStorage FVB - // - { - NV_STORAGE_BASE_ADDRESS, - { - {0,}, //ZeroVector[16] - EFI_SYSTEM_NV_DATA_FV_GUID, - FVB_MEDIA_BLOCK_SIZE * SYSTEM_NV_BLOCK_NUM, - EFI_FVH_SIGNATURE, - 0x0004feff, // check MdePkg/Include/Pi/PiFirmwareVolume.h for details on EFI_FVB_ATTRIBUTES_2 - sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), - 0, //CheckSum which will be calucated dynamically. - 0, //ExtHeaderOffset - {0,}, //Reserved[1] - 2, //Revision - { - { - SYSTEM_NV_BLOCK_NUM, - FVB_MEDIA_BLOCK_SIZE, - } - } - }, - { - { - 0, - 0 - } - } +/** + Returns FVB media information for NV variable storage. + + @return FvbMediaInfo A pointer to an instance of FVB media info produced by this function. + The buffer is allocated internally to this function and it is the caller's + responsibility to free the memory + +**/ +typedef +EFI_STATUS +(*FVB_MEDIA_INFO_GENERATOR)( + OUT EFI_FVB2_MEDIA_INFO *FvbMediaInfo + ); + +/** + Returns FVB media information for NV variable storage. + + @param[out] FvbMediaInfo A pointer to an instance of FVB media info produced by this function. + + @retval EFI_SUCCESS A structure was successfully written to the FvbMediaInfo buffer. + @retval EFI_INVALID_PARAMETER The FvbMediaInfo parameter is NULL. + @retval EFI_UNSUPPORTED An error occurred retrieving variable FV information. + @retval EFI_BAD_BUFFER_SIZE An overflow or underflow of the FV buffer occurred with the information found. + +**/ +EFI_STATUS +GenerateNvStorageFvbMediaInfo ( + OUT EFI_FVB2_MEDIA_INFO *FvbMediaInfo + ) +{ + EFI_STATUS Status; + UINT32 NvBlockNum; + UINT32 TotalNvVariableStorageSize; + EFI_PHYSICAL_ADDRESS NvStorageBaseAddress; + EFI_FIRMWARE_VOLUME_HEADER FvbInfo = { + {0,}, //ZeroVector[16] + EFI_SYSTEM_NV_DATA_FV_GUID, //FileSystemGuid + 0, //FvLength + EFI_FVH_SIGNATURE, //Signature + 0x0004feff, //Attributes + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + //HeaderLength + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, //Checksum + 0, //ExtHeaderOffset + {0,}, //Reserved[1] + 2, //Revision + { //BlockMap[1] + {0,0} + } + }; + + if (FvbMediaInfo == NULL) { + return EFI_INVALID_PARAMETER; } + + ZeroMem (FvbMediaInfo, sizeof (*FvbMediaInfo)); + + GetVariableFvInfo (&NvStorageBaseAddress, &TotalNvVariableStorageSize); + if ((NvStorageBaseAddress == 0) || (TotalNvVariableStorageSize == 0)) { + return EFI_UNSUPPORTED; + } + + NvBlockNum = TotalNvVariableStorageSize / FVB_MEDIA_BLOCK_SIZE; + + Status = SafeUint64Mult ((UINT64)NvBlockNum, FVB_MEDIA_BLOCK_SIZE, &FvbInfo.FvLength); + if (EFI_ERROR (Status)) { + return EFI_BAD_BUFFER_SIZE; + } + + FvbInfo.BlockMap[0].NumBlocks = NvBlockNum; + FvbInfo.BlockMap[0].Length = FVB_MEDIA_BLOCK_SIZE; + + FvbMediaInfo->BaseAddress = NvStorageBaseAddress; + CopyMem (&FvbMediaInfo->FvbInfo, &FvbInfo, sizeof (FvbInfo)); + + return EFI_SUCCESS; +} + +FVB_MEDIA_INFO_GENERATOR mFvbMediaInfoGenerators[] = { + GenerateNvStorageFvbMediaInfo }; EFI_STATUS @@ -64,12 +106,16 @@ GetFvbInfo ( OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo ) { + EFI_STATUS Status; + EFI_FVB2_MEDIA_INFO FvbMediaInfo; UINTN Index; EFI_FIRMWARE_VOLUME_HEADER *FvHeader; - for (Index = 0; Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB2_MEDIA_INFO); Index++) { - if (mPlatformFvbMediaInfo[Index].BaseAddress == FvBaseAddress) { - FvHeader = &mPlatformFvbMediaInfo[Index].FvbInfo; + for (Index = 0; Index < ARRAY_SIZE (mFvbMediaInfoGenerators); Index++) { + Status = mFvbMediaInfoGenerators[Index](&FvbMediaInfo); + ASSERT_EFI_ERROR (Status); + if (!EFI_ERROR (Status) && (FvbMediaInfo.BaseAddress == FvBaseAddress)) { + FvHeader = AllocateCopyPool (sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvbMediaInfo.FvbInfo); // // Update the checksum value of FV header. diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c index 8e5d6a1f83..c55daabb5e 100644 --- a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c @@ -3,6 +3,7 @@ which are compliant with the Intel(R) Serial Flash Interface Compatibility Specification. Copyright (c) 2017, Intel Corporation. All rights reserved.
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -25,12 +26,6 @@ FV_INFO mPlatformFvBaseAddress[] = { {0, 0} }; -FV_INFO mPlatformDefaultBaseAddress[] = { - {0, 0}, // {FixedPcdGet32(PcdFlashNvStorageVariableBase), FixedPcdGet32(PcdFlashNvStorageVariableSize)}, - {0, 0}, // {FixedPcdGet32(PcdFlashMicrocodeFvBase), FixedPcdGet32(PcdFlashMicrocodeFvSize)}, - {0, 0} -}; - FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = { { { @@ -530,6 +525,85 @@ FvbSetVolumeAttributes ( return EFI_SUCCESS; } +/** + Get the total size of the firmware volume on flash used for variable store operations. + + @param[out] BaseAddress Base address of the variable store firmware volume. + @param[out] Length Length in bytes of the firmware volume used for variable store operations. + +**/ +VOID +GetVariableFvInfo ( + OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + OUT UINT32 *Length + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS NvBaseAddress; + EFI_PHYSICAL_ADDRESS NvVariableBaseAddress; + UINT64 Length64; + UINT32 NvStoreLength; + UINT32 FtwSpareLength; + UINT32 FtwWorkingLength; + UINT32 TotalLength; + + TotalLength = 0; + Status = EFI_SUCCESS; + + if ((BaseAddress == NULL) || (Length == NULL)) { + ASSERT ((BaseAddress != NULL) && (Length != NULL)); + return; + } + *BaseAddress = 0; + *Length = 0; + + Status = GetVariableFlashNvStorageInfo (&NvBaseAddress, &Length64); + if (!EFI_ERROR (Status)) { + NvVariableBaseAddress = NvBaseAddress; + // Stay within the current UINT32 size assumptions in the variable stack. + Status = SafeUint64ToUint32 (Length64, &NvStoreLength); + } + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + Status = GetVariableFlashFtwSpareInfo (&NvBaseAddress, &Length64); + if (!EFI_ERROR (Status)) { + // Stay within the current UINT32 size assumptions in the variable stack. + Status = SafeUint64ToUint32 (Length64, &FtwSpareLength); + } + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + Status = GetVariableFlashFtwWorkingInfo (&NvBaseAddress, &Length64); + if (!EFI_ERROR (Status)) { + // Stay within the current UINT32 size assumptions in the variable stack. + Status = SafeUint64ToUint32 (Length64, &FtwWorkingLength); + } + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + Status = SafeUint32Add (NvStoreLength, FtwSpareLength, &TotalLength); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + Status = SafeUint32Add (TotalLength, FtwWorkingLength, &TotalLength); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return; + } + + *BaseAddress = NvVariableBaseAddress; + *Length = TotalLength; +} + /** Check the integrity of firmware volume header @@ -545,7 +619,12 @@ IsFvHeaderValid ( IN CONST EFI_FIRMWARE_VOLUME_HEADER *FvHeader ) { - if (FvBase == PcdGet32(PcdFlashNvStorageVariableBase)) { + EFI_PHYSICAL_ADDRESS NvStorageFvBaseAddress; + UINT32 NvStorageSize; + + GetVariableFvInfo (&NvStorageFvBaseAddress, &NvStorageSize); + + if (FvBase == NvStorageFvBaseAddress) { if (CompareMem (&FvHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid, sizeof(EFI_GUID)) != 0 ) { return FALSE; } diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h index 6f7ae0648a..cef442160d 100644 --- a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h @@ -2,6 +2,7 @@ Common source definitions used in serial flash drivers Copyright (c) 2017, Intel Corporation. All rights reserved.
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -12,6 +13,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -24,6 +26,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include +#include #include @@ -148,11 +152,23 @@ GetFvbInfo ( OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo ); +/** + Get the total size of the firmware volume on flash used for variable store operations. + + @param[out] BaseAddress Base address of the variable store firmware volume. + @param[out] Length Length in bytes of the firmware volume used for variable store operations. + +**/ +VOID +GetVariableFvInfo ( + OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + OUT UINT32 *Length + ); + extern FVB_GLOBAL mFvbModuleGlobal; extern FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate; extern FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate; extern EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL mFvbProtocolTemplate; extern FV_INFO mPlatformFvBaseAddress[]; -extern FV_INFO mPlatformDefaultBaseAddress[]; #endif diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c index 835c212086..a73b5900bc 100644 --- a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c @@ -113,15 +113,31 @@ FvbInitialize ( UINT32 MaxLbaSize; UINT32 BytesWritten; UINTN BytesErased; + UINT64 NvStorageFvSize; + + Status = GetVariableFlashNvStorageInfo (&BaseAddress, &NvStorageFvSize); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_ERROR, "[%a] - An error ocurred getting variable info - %r.\n", __FUNCTION__, Status)); + return; + } + + // Stay within the current UINT32 size assumptions in the variable stack. + Status = SafeUint64ToUint32 (BaseAddress, &mPlatformFvBaseAddress[0].FvBase); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_ERROR, "[%a] - 64-bit variable storage base address not supported.\n", __FUNCTION__)); + return; + } + Status = SafeUint64ToUint32 (NvStorageFvSize, &mPlatformFvBaseAddress[0].FvSize); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_ERROR, "[%a] - 64-bit variable storage size not supported.\n", __FUNCTION__)); + return; + } - mPlatformFvBaseAddress[0].FvBase = PcdGet32(PcdFlashNvStorageVariableBase); - mPlatformFvBaseAddress[0].FvSize = PcdGet32(PcdFlashNvStorageVariableSize); mPlatformFvBaseAddress[1].FvBase = PcdGet32(PcdFlashMicrocodeFvBase); mPlatformFvBaseAddress[1].FvSize = PcdGet32(PcdFlashMicrocodeFvSize); - mPlatformDefaultBaseAddress[0].FvBase = PcdGet32(PcdFlashNvStorageVariableBase); - mPlatformDefaultBaseAddress[0].FvSize = PcdGet32(PcdFlashNvStorageVariableSize); - mPlatformDefaultBaseAddress[1].FvBase = PcdGet32(PcdFlashMicrocodeFvBase); - mPlatformDefaultBaseAddress[1].FvSize = PcdGet32(PcdFlashMicrocodeFvSize); // // We will only continue with FVB installation if the @@ -143,7 +159,8 @@ FvbInitialize ( BytesWritten = 0; BytesErased = 0; DEBUG ((DEBUG_ERROR, "ERROR - The FV in 0x%x is invalid!\n", FvHeader)); - Status = GetFvbInfo (BaseAddress, &FvHeader); + FvHeader = NULL; + Status = GetFvbInfo (BaseAddress, &FvHeader); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "ERROR - Can't recovery FV header at 0x%x. GetFvbInfo Status %r\n", BaseAddress, Status)); continue; @@ -156,27 +173,42 @@ FvbInitialize ( Status = SpiFlashBlockErase( (UINTN) BaseAddress, &BytesErased); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "ERROR - SpiFlashBlockErase Error %r\n", Status)); + if (FvHeader != NULL) { + FreePool (FvHeader); + } continue; } if (BytesErased != FvHeader->BlockMap->Length) { DEBUG ((DEBUG_WARN, "ERROR - BytesErased != FvHeader->BlockMap->Length\n")); DEBUG ((DEBUG_INFO, " BytesErased = 0x%X\n Length = 0x%X\n", BytesErased, FvHeader->BlockMap->Length)); + if (FvHeader != NULL) { + FreePool (FvHeader); + } continue; } BytesWritten = FvHeader->HeaderLength; Status = SpiFlashWrite ((UINTN)BaseAddress, &BytesWritten, (UINT8*)FvHeader); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "ERROR - SpiFlashWrite Error %r\n", Status)); + if (FvHeader != NULL) { + FreePool (FvHeader); + } continue; } if (BytesWritten != FvHeader->HeaderLength) { DEBUG ((DEBUG_WARN, "ERROR - BytesWritten != HeaderLength\n")); DEBUG ((DEBUG_INFO, " BytesWritten = 0x%X\n HeaderLength = 0x%X\n", BytesWritten, FvHeader->HeaderLength)); + if (FvHeader != NULL) { + FreePool (FvHeader); + } continue; } Status = SpiFlashLock (); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "ERROR - SpiFlashLock Error %r\n", Status)); + if (FvHeader != NULL) { + FreePool (FvHeader); + } continue; } DEBUG ((DEBUG_INFO, "FV Header @ 0x%X restored with static data\n", BaseAddress)); @@ -184,6 +216,9 @@ FvbInitialize ( // Clear cache for this range. // WriteBackInvalidateDataCacheRange ( (VOID *) (UINTN) BaseAddress, FvHeader->BlockMap->Length); + if (FvHeader != NULL) { + FreePool (FvHeader); + } } } diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf index b5c7f1ca81..a2f2d80ecc 100644 --- a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf @@ -32,8 +32,10 @@ BaseLib UefiBootServicesTableLib UefiDriverEntryPoint + SafeIntLib SpiFlashCommonLib MmServicesTableLib + VariableFlashInfoLib [Packages] MdePkg/MdePkg.dec @@ -41,10 +43,6 @@ IntelSiliconPkg/IntelSiliconPkg.dec [Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase ## CONSUMES gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize ## CONSUMES diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf index bb957b614d..fc4f2fb5d0 100644 --- a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf +++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf @@ -31,8 +31,10 @@ MemoryAllocationLib PcdLib MmServicesTableLib + SafeIntLib SpiFlashCommonLib StandaloneMmDriverEntryPoint + VariableFlashInfoLib [Packages] MdePkg/MdePkg.dec @@ -40,10 +42,6 @@ IntelSiliconPkg/IntelSiliconPkg.dec [Pcd] - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize ## CONSUMES - gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize ## CONSUMES gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvBase ## CONSUMES gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize ## CONSUMES diff --git a/IntelSiliconPkg/IntelSiliconPkg.dsc b/IntelSiliconPkg/IntelSiliconPkg.dsc index 8af66b2f00..d3d8ef61b9 100644 --- a/IntelSiliconPkg/IntelSiliconPkg.dsc +++ b/IntelSiliconPkg/IntelSiliconPkg.dsc @@ -40,9 +40,11 @@ PeiGetVtdPmrAlignmentLib|IntelSiliconPkg/Library/PeiGetVtdPmrAlignmentLib/PeiGetVtdPmrAlignmentLib.inf TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf + SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf SpiFlashCommonLib|IntelSiliconPkg/Library/SpiFlashCommonLibNull/SpiFlashCommonLibNull.inf UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf [LibraryClasses.common.PEIM] PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf @@ -63,11 +65,16 @@ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf [LibraryClasses.common.DXE_SMM_DRIVER] + DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf [LibraryClasses.common.MM_STANDALONE] + HobLib|StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf MemoryAllocationLib|StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf From 7d7d7e492afba3124fb3a2af109e877b48b552d5 Mon Sep 17 00:00:00 2001 From: Sheng Wei Date: Wed, 17 Aug 2022 14:11:17 +0800 Subject: [PATCH 25/26] IntelSiliconPkg/VTd: Add DMAR SIDP Table dumpping VT-d spec 4.0 has added a new structure called SIDP which is more generic to describe special properties of integrated devices. Reviewed-by: Robert Kowalewski Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Jenny Huang Signed-off-by: Sheng Wei --- .../Feature/VTd/IntelVTdDxe/DmarAcpiTable.c | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c index f8fdb2a781..6284045853 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c @@ -93,6 +93,10 @@ DumpDmarDeviceScopeEntry ( " Length ............................................. 0x%02x\n", DmarDeviceScopeEntry->Length )); + DEBUG ((DEBUG_INFO, + " Flags .............................................. 0x%02x\n", + DmarDeviceScopeEntry->Flags + )); DEBUG ((DEBUG_INFO, " Enumeration ID ..................................... 0x%02x\n", DmarDeviceScopeEntry->EnumerationId @@ -122,6 +126,66 @@ DumpDmarDeviceScopeEntry ( return; } +/** + Dump DMAR SIDP table. + + @param[in] Sidp DMAR SIDP table +**/ +VOID +DumpDmarSidp ( + IN EFI_ACPI_DMAR_SIDP_HEADER *Sidp + ) +{ + EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry; + INTN SidpLen; + + if (Sidp == NULL) { + return; + } + + DEBUG ((DEBUG_INFO, + " ***************************************************************************\n" + )); + DEBUG ((DEBUG_INFO, + " * SoC Integrated Device Property Reporting Structure *\n" + )); + DEBUG ((DEBUG_INFO, + " ***************************************************************************\n" + )); + DEBUG ((DEBUG_INFO, + (sizeof(UINTN) == sizeof(UINT64)) ? + " SIDP address ........................................... 0x%016lx\n" : + " SIDP address ........................................... 0x%08x\n", + Sidp + )); + DEBUG ((DEBUG_INFO, + " Type ................................................. 0x%04x\n", + Sidp->Header.Type + )); + DEBUG ((DEBUG_INFO, + " Length ............................................... 0x%04x\n", + Sidp->Header.Length + )); + DEBUG ((DEBUG_INFO, + " Segment Number ....................................... 0x%04x\n", + Sidp->SegmentNumber + )); + + SidpLen = Sidp->Header.Length - sizeof(EFI_ACPI_DMAR_SIDP_HEADER); + DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Sidp + 1); + while (SidpLen > 0) { + DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); + SidpLen -= DmarDeviceScopeEntry->Length; + DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length); + } + + DEBUG ((DEBUG_INFO, + " ***************************************************************************\n\n" + )); + + return; +} + /** Dump DMAR SATC table. @@ -472,6 +536,10 @@ DumpDmarDrhd ( " Flags ................................................ 0x%02x\n", Drhd->Flags )); + DEBUG ((DEBUG_INFO, + " Size ................................................. 0x%02x\n", + Drhd->Size + )); DEBUG ((DEBUG_INFO, " INCLUDE_PCI_ALL .................................... 0x%02x\n", Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL @@ -583,7 +651,11 @@ DumpAcpiDMAR ( case EFI_ACPI_DMAR_TYPE_SATC: DumpDmarSatc ((EFI_ACPI_DMAR_SATC_HEADER *)DmarHeader); break; + case EFI_ACPI_DMAR_TYPE_SIDP: + DumpDmarSidp ((EFI_ACPI_DMAR_SIDP_HEADER *)DmarHeader); + break; default: + DEBUG ((DEBUG_INFO, "Unknown DMAR Table Type : %d\n", DmarHeader->Type)); break; } DmarLen -= DmarHeader->Length; From 178ca712e0340a59c334ff4809ae1b2ff3ffe66e Mon Sep 17 00:00:00 2001 From: Deepak Singh Date: Tue, 23 Aug 2022 01:44:11 -0700 Subject: [PATCH 26/26] IntelSiliconPkg: Fix DEBUG macros having incorrect number of arguments REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4027 Cc: Ray Ni Cc: Rangasai V Chaganty Cc: Isaac Oram Cc: Ashraf Ali S Cc: Ovais F Pir Signed-off-by: Deepak Singh Reviewed-by: Isaac Oram --- .../IntelPciDeviceSecurityDxe/IntelPciDeviceSecurityDxe.c | 2 +- IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/IntelSiliconPkg/Feature/PcieSecurity/IntelPciDeviceSecurityDxe/IntelPciDeviceSecurityDxe.c b/IntelSiliconPkg/Feature/PcieSecurity/IntelPciDeviceSecurityDxe/IntelPciDeviceSecurityDxe.c index b09a1c2953..4fa41e9721 100644 --- a/IntelSiliconPkg/Feature/PcieSecurity/IntelPciDeviceSecurityDxe/IntelPciDeviceSecurityDxe.c +++ b/IntelSiliconPkg/Feature/PcieSecurity/IntelPciDeviceSecurityDxe/IntelPciDeviceSecurityDxe.c @@ -488,7 +488,7 @@ DoMeasurementsFromDigestRegister ( DEBUG((DEBUG_INFO, "\n")); } - DEBUG((DEBUG_INFO, "ExtendDigestRegister...\n", ExtendDigestRegister)); + DEBUG((DEBUG_INFO, "ExtendDigestRegister...\n")); ExtendDigestRegister (PciIo, DeviceSecurityPolicy, TcgAlgId, DigestSel, Digest, DeviceSecurityState); } } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c index a193d6bba4..d1066322f6 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c @@ -642,7 +642,7 @@ DumpVtdVerRegs ( IN VTD_VER_REG *VerReg ) { - DEBUG ((DEBUG_INFO, " VerReg:\n", VerReg->Uint32)); + DEBUG ((DEBUG_INFO, " VerReg - 0x%x\n", VerReg->Uint32)); DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major)); DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor)); } @@ -657,7 +657,7 @@ DumpVtdCapRegs ( IN VTD_CAP_REG *CapReg ) { - DEBUG((DEBUG_INFO, " CapReg:\n", CapReg->Uint64)); + DEBUG((DEBUG_INFO, " CapReg - 0x%x\n", CapReg->Uint64)); DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND)); DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL)); DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF)); @@ -688,7 +688,7 @@ DumpVtdECapRegs ( IN VTD_ECAP_REG *ECapReg ) { - DEBUG((DEBUG_INFO, " ECapReg:\n", ECapReg->Uint64)); + DEBUG((DEBUG_INFO, " ECapReg - 0x%x\n", ECapReg->Uint64)); DEBUG((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C)); DEBUG((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI)); DEBUG((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT));