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