Merge branch 'upstream-edk2-platforms' into upstream

This commit is contained in:
Ken Lautner 2022-09-28 10:54:16 -07:00
Родитель ba8bc85498 178ca712e0
Коммит 8a5664f7ff
38 изменённых файлов: 3700 добавлений и 1286 удалений

Просмотреть файл

@ -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.<BR>
Copyright (c) Microsoft Corporation.<BR>
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;
}

Просмотреть файл

@ -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.<BR>
Copyright (c) Microsoft Corporation.<BR>
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;
}

Просмотреть файл

@ -0,0 +1,174 @@
/** @file
Common source definitions used in serial flash drivers
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _SPI_FVB_SERVICE_COMMON_H
#define _SPI_FVB_SERVICE_COMMON_H
#include <Guid/EventGroup.h>
#include <Guid/FirmwareFileSystem2.h>
#include <Guid/SystemNvDataGuid.h>
#include <Pi/PiFirmwareVolume.h>
#include <Protocol/DevicePath.h>
#include <Protocol/FirmwareVolumeBlock.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/IoLib.h>
#include <Library/CacheMaintenanceLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/DevicePathLib.h>
#include <Library/HobLib.h>
#include <Library/VariableFlashInfoLib.h>
#include <Library/SafeIntLib.h>
#include <Library/SpiFlashCommonLib.h>
//
// 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

Просмотреть файл

@ -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.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "SpiFvbServiceCommon.h"
#include <Library/MmServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Protocol/SmmFirmwareVolumeBlock.h>
/**
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)));
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
/** @file
Definitions common to MM implementation in this driver.
Copyright (c) Microsoft Corporation.<BR>
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

Просмотреть файл

@ -0,0 +1,66 @@
### @file
# Component description file for the Serial Flash device Runtime driver.
#
# Copyright (c) 2017-2019, Intel Corporation. All rights reserved.<BR>
# Copyright (c) Microsoft Corporation.<BR>
#
# 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

Просмотреть файл

@ -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.<BR>
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;
}

Просмотреть файл

@ -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.<BR>
# Copyright (c) Microsoft Corporation.<BR>
#
# 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

Просмотреть файл

@ -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.<BR>
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;
}

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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
//

Просмотреть файл

@ -1,6 +1,7 @@
/** @file
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
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;
}

Просмотреть файл

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
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;
}

Просмотреть файл

@ -1,6 +1,6 @@
/** @file
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@ -23,6 +23,8 @@
#include <Guid/VtdPmrInfoHob.h>
#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;
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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.<BR>
# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
# 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

Просмотреть файл

@ -1,6 +1,7 @@
/** @file
Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
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;
}

Просмотреть файл

@ -33,6 +33,7 @@
#include <Protocol/PciEnumerationComplete.h>
#include <Protocol/PlatformVtdPolicy.h>
#include <Protocol/IoMmu.h>
#include <Protocol/PciRootBridgeIo.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/DmaRemappingReportingTable.h>
@ -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.

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -70,6 +70,7 @@
gEfiPciIoProtocolGuid ## CONSUMES
gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
gEdkiiPlatformVTdPolicyProtocolGuid ## SOMETIMES_CONSUMES
gEfiPciRootBridgeIoProtocolGuid ## CONSUMES
[Pcd]
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES

Просмотреть файл

@ -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.

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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));
}
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -0,0 +1,45 @@
/** @file
Flash region GUID definitions.
Copyright (c) Microsoft Corporation.<BR>
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

Просмотреть файл

@ -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

Просмотреть файл

@ -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];

Просмотреть файл

@ -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. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __SPI_FLASH_COMMON_LIB_H__
#define __SPI_FLASH_COMMON_LIB_H__
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/PcdLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#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

Просмотреть файл

@ -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.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _PCH_SPI2_PPI_H_
#define _PCH_SPI2_PPI_H_
#include <Protocol/Spi2.h>
//
// 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

Просмотреть файл

@ -0,0 +1,94 @@
/** @file
IntelDieInfo definition
Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
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.
<b>Revision 1</b>:
- 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_

Просмотреть файл

@ -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.<BR>
Copyright (c) Microsoft Corporation.<BR>
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

Просмотреть файл

@ -4,6 +4,7 @@
# This package provides common open source Intel silicon modules.
#
# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) Microsoft Corporation.<BR>
# 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.<BR><BR>
# 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.<BR><BR>
# EDKII_ERROR_CODE_VTD_ERROR = (EFI_IO_BUS_UNSPECIFIED | (EFI_OEM_SPECIFIC | 0x00000000)) = 0x02008000<BR>

Просмотреть файл

@ -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

Просмотреть файл

@ -0,0 +1,60 @@
/** @file
SMM Library instance of SPI Flash Common Library Class
Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/SmmServicesTableLib.h>
#include <Protocol/Spi2.h>
#include <Library/DebugLib.h>
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;
}

Просмотреть файл

@ -0,0 +1,51 @@
## @file
# SMM Library instance of Spi Flash Common Library Class
#
# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
# 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

Просмотреть файл

@ -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.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/SpiFlashCommonLib.h>
#include <Library/IoLib.h>
#include <Protocol/Spi2.h>
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;
}

Просмотреть файл

@ -0,0 +1,101 @@
/** @file
Null Library instance of SPI Flash Common Library Class
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/SpiFlashCommonLib.h>
/**
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;
}

Просмотреть файл

@ -0,0 +1,28 @@
### @file
# NULL instance of Spi Flash Common Library Class
#
# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
#
# 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