Merge branch 'upstream-edk2-platforms' into upstream
This commit is contained in:
Коммит
8a5664f7ff
|
@ -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
|
Загрузка…
Ссылка в новой задаче