diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c
new file mode 100644
index 0000000000..e3720bbb34
--- /dev/null
+++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/FvbInfo.c
@@ -0,0 +1,140 @@
+/**@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.
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SpiFvbServiceCommon.h"
+
+#define FIRMWARE_BLOCK_SIZE 0x10000
+#define FVB_MEDIA_BLOCK_SIZE FIRMWARE_BLOCK_SIZE
+typedef struct {
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ EFI_FIRMWARE_VOLUME_HEADER FvbInfo;
+ EFI_FV_BLOCK_MAP_ENTRY End[1];
+} EFI_FVB2_MEDIA_INFO;
+
+/**
+ 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
+GetFvbInfo (
+ IN EFI_PHYSICAL_ADDRESS FvBaseAddress,
+ 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 < 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.
+ //
+ 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..c55daabb5e
--- /dev/null
+++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.c
@@ -0,0 +1,982 @@
+/** @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.
+Copyright (c) Microsoft Corporation.
+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_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;
+}
+
+/**
+ 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
+
+ @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
+ )
+{
+ EFI_PHYSICAL_ADDRESS NvStorageFvBaseAddress;
+ UINT32 NvStorageSize;
+
+ GetVariableFvInfo (&NvStorageFvBaseAddress, &NvStorageSize);
+
+ if (FvBase == NvStorageFvBaseAddress) {
+ 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..cef442160d
--- /dev/null
+++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceCommon.h
@@ -0,0 +1,174 @@
+/** @file
+ 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
+
+**/
+
+#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
+#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
+ );
+
+/**
+ 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[];
+
+#endif
diff --git a/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c
new file mode 100644
index 0000000000..a73b5900bc
--- /dev/null
+++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceMm.c
@@ -0,0 +1,306 @@
+/** @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;
+ 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[1].FvBase = PcdGet32(PcdFlashMicrocodeFvBase);
+ mPlatformFvBaseAddress[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));
+ 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;
+ }
+ 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));
+ 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));
+ //
+ // Clear cache for this range.
+ //
+ WriteBackInvalidateDataCacheRange ( (VOID *) (UINTN) BaseAddress, FvHeader->BlockMap->Length);
+ if (FvHeader != NULL) {
+ FreePool (FvHeader);
+ }
+ }
+ }
+
+ //
+ // 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..a2f2d80ecc
--- /dev/null
+++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceSmm.inf
@@ -0,0 +1,66 @@
+### @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
+ SafeIntLib
+ SpiFlashCommonLib
+ MmServicesTableLib
+ VariableFlashInfoLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelSiliconPkg/IntelSiliconPkg.dec
+
+[Pcd]
+ 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..fc4f2fb5d0
--- /dev/null
+++ b/IntelSiliconPkg/Feature/Flash/SpiFvbService/SpiFvbServiceStandaloneMm.inf
@@ -0,0 +1,65 @@
+### @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
+ SafeIntLib
+ SpiFlashCommonLib
+ StandaloneMmDriverEntryPoint
+ VariableFlashInfoLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelSiliconPkg/IntelSiliconPkg.dec
+
+[Pcd]
+ 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/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/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
//
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index 67e5f06fe1..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 DHRD table.
-
- @param[in] VTdUnitInfo The VTd engine unit information.
- @param[in] DmarDrhd The DRHD table.
-
-**/
-VOID
-ProcessDhrd (
- 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," ProcessDhrd: with INCLUDE ALL\n"));
- } else {
- VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE;
- DEBUG ((DEBUG_INFO," ProcessDhrd: 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," ProcessDhrd: "));
- 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);
- ProcessDhrd (&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 40ba88c66b..f9a06619d7 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 - 2022, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -83,73 +83,69 @@ PerpareCacheInvalidationInterface (
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;
+ 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", VTdUnitInfo->QiDescLength));
- Reg64 = (UINT64)(UINTN)VTdUnitInfo->QiDesc;
+ Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc;
Reg64 |= QueueSize;
- MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, Reg64);
+ 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,19 +163,19 @@ DisableQueuedInvalidationInterface (
IN VTD_UNIT_INFO *VTdUnitInfo
)
{
- UINT32 Reg32;
+ UINT32 Reg32;
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));
+ FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES (sizeof (QI_DESC) * VTdUnitInfo->QiDescLength));
VTdUnitInfo->QiDesc = NULL;
VTdUnitInfo->QiDescLength = 0;
}
@@ -203,26 +199,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;
}
@@ -259,7 +240,7 @@ SubmitQueuedInvalidationDescriptor (
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;
@@ -268,12 +249,11 @@ 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);
//
// 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 +263,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 +287,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 {
//
@@ -345,33 +325,34 @@ InvalidateIOTLB (
{
UINT64 Reg64;
VTD_ECAP_REG ECapReg;
+ VTD_CAP_REG CapReg;
QI_DESC QiDesc;
if (VTdUnitInfo->EnableQueuedInvalidation == 0) {
//
// 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);
- 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);
@@ -381,10 +362,10 @@ 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] 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 +373,15 @@ InvalidateIOTLB (
EFI_STATUS
EnableDmarPreMem (
IN UINTN VtdUnitBaseAddress,
- IN UINTN RootEntryTable
+ IN UINT64 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%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);
@@ -417,7 +398,7 @@ EnableDmarPreMem (
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
//
- // Write Buffer Flush before invalidation
+ // Write Buffer Flush
//
FlushWriteBuffer (VtdUnitBaseAddress);
@@ -452,30 +433,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 +474,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,131 +550,55 @@ 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));
-}
+ DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", FixedPcdGetBool (PcdVTdSupportAbortDmaMode)));
-/**
- Dump VTd extended capability registers.
+ ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
+ DEBUG ((DEBUG_INFO, "ECapReg.ADMS : %d\n", ECapReg.Bits.ADMS));
- @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, " 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));
- 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));
-}
-
-
-/**
- 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));
-
- 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;
+ if ((ECapReg.Bits.ADMS == 1) && FixedPcdGetBool (PcdVTdSupportAbortDmaMode)) {
+ //
+ // 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;
}
-
- 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);
-
- EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable);
+ DEBUG ((DEBUG_INFO, "Block All DMA by TE.\n"));
+ Status = EnableDmarPreMem (VtdUnitBaseAddress, (UINT64) (*RootEntryTable));
}
- return;
+ return Status;
}
/**
@@ -707,20 +615,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 | BIT11);
} 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;
}
@@ -729,23 +645,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]);
}
@@ -778,6 +693,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.
@@ -790,43 +743,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..0a0dc22a23 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 UINTN 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 UINTN 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..fad57f5ced 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;
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 UINTN 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/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/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
index 9391e298f3..c6fe86daa1 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)) {
@@ -884,13 +896,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 = CreateContextEntry (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;
}
@@ -898,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;
-}
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..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;
@@ -662,7 +734,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 +742,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,15 +762,15 @@ 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 = ScanPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, 0, ScanBusCallbackRegisterPciDevice);
+ Status = ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, ScanBusCallbackRegisterPciDevice);
if (EFI_ERROR (Status)) {
return Status;
}
} 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 +781,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 +949,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/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.
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
index 61d5b3f91f..ea7e48a4c5 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 = CreateContextEntry (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 7704e4f360..d1066322f6 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;
@@ -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;
@@ -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));
@@ -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/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;
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/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
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];
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/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/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/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 92be71de5d..84e90b858b 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
#
##
@@ -46,6 +47,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}
@@ -70,12 +75,47 @@
## 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 } }
+
+ ## 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
+
+ # 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 }}
+ gIntelDieInfoProtocolGuid = { 0xAED8A0A1, 0xFDE6, 0x4CF2, { 0xA3, 0x85, 0x08, 0xF1, 0x25, 0xF2, 0x40, 0x37 }}
## Protocol for device security policy.
# Include/Protocol/PlatformDeviceSecurityPolicy.h
@@ -88,6 +128,19 @@
# @Prompt Shadow all microcode update patches.
gIntelSiliconPkgTokenSpaceGuid.PcdShadowAllMicrocode|FALSE|BOOLEAN|0x00000006
+[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
+
+ ## 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
diff --git a/IntelSiliconPkg/IntelSiliconPkg.dsc b/IntelSiliconPkg/IntelSiliconPkg.dsc
index ffb7237d1d..d3d8ef61b9 100644
--- a/IntelSiliconPkg/IntelSiliconPkg.dsc
+++ b/IntelSiliconPkg/IntelSiliconPkg.dsc
@@ -40,6 +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
@@ -59,6 +64,21 @@
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
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
+
###################################################################################################
#
# Components Section - list of the modules and components that will be processed by compilation
@@ -82,6 +102,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
@@ -94,6 +116,8 @@
IntelSiliconPkg/Library/PeiDxeSmmBootMediaLib/DxeSmmFirmwareBootMediaLib.inf
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..c636be4e48
--- /dev/null
+++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.c
@@ -0,0 +1,60 @@
+/** @file
+ 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
+
+extern PCH_SPI2_PROTOCOL *mSpi2Protocol;
+
+extern UINTN mBiosAreaBaseAddress;
+extern UINTN mBiosSize;
+extern UINTN mBiosOffset;
+
+/**
+ The library constructor.
+
+ 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 SPI2 protocol.
+ //
+ Status = gSmst->SmmLocateProtocol (
+ &gPchSmmSpi2ProtocolGuid,
+ NULL,
+ (VOID **) &mSpi2Protocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ mSpi2Protocol->GetRegionAddress (mSpi2Protocol, &gFlashRegionBiosGuid, &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..312e38d589
--- /dev/null
+++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SmmSpiFlashCommonLib.inf
@@ -0,0 +1,51 @@
+## @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
+
+[Guids]
+ gFlashRegionBiosGuid
+
+[Sources]
+ SmmSpiFlashCommonLib.c
+ SpiFlashCommon.c
+
+[Protocols]
+ gPchSmmSpi2ProtocolGuid ## CONSUMES
+
+[Depex.X64.DXE_SMM_DRIVER]
+ gPchSmmSpi2ProtocolGuid
diff --git a/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
new file mode 100644
index 0000000000..3e97aadbfe
--- /dev/null
+++ b/IntelSiliconPkg/Library/SmmSpiFlashCommonLib/SpiFlashCommon.c
@@ -0,0 +1,209 @@
+/** @file
+ Wrap PCH_SPI2_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_SPI2_PROTOCOL *mSpi2Protocol;
+
+//
+// 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 = mSpi2Protocol->FlashWrite (
+ mSpi2Protocol,
+ &gFlashRegionBiosGuid,
+ (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 = mSpi2Protocol->FlashErase (
+ mSpi2Protocol,
+ &gFlashRegionBiosGuid,
+ (UINT32) Offset,
+ (UINT32) RemainingBytes
+ );
+ return Status;
+}
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