Remove IntelSiliconPkg that has been moved to edk2-platform repo

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=1890

Signed-off-by: Liming Gao <liming.gao@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Sai Chaganty <rangasai.v.chaganty@intel.com>
This commit is contained in:
Liming Gao 2019-06-10 23:27:58 +08:00
parent 370f16c548
commit 77ff7d6aa2
56 changed files with 0 additions and 12948 deletions

View File

@ -1,36 +0,0 @@
/** @file
Microcode flash device access library NULL instance.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiDxe.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MicrocodeFlashAccessLib.h>
/**
Perform microcode write opreation.
@param[in] FlashAddress The address of flash device to be accessed.
@param[in] Buffer The pointer to the data buffer.
@param[in] Length The length of data buffer in bytes.
@retval EFI_SUCCESS The operation returns successfully.
@retval EFI_WRITE_PROTECTED The flash device is read only.
@retval EFI_UNSUPPORTED The flash device access is unsupported.
@retval EFI_INVALID_PARAMETER The input parameter is not valid.
**/
EFI_STATUS
EFIAPI
MicrocodeFlashWrite (
IN EFI_PHYSICAL_ADDRESS FlashAddress,
IN VOID *Buffer,
IN UINTN Length
)
{
CopyMem((VOID *)(UINTN)(FlashAddress), Buffer, Length);
return EFI_SUCCESS;
}

View File

@ -1,34 +0,0 @@
## @file
# Microcode flash device access library.
#
# Microcode flash device access library NULL instance.
#
# Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = MicrocodeFlashAccessLibNull
MODULE_UNI_FILE = MicrocodeFlashAccessLibNull.uni
FILE_GUID = 6F871ADD-9D86-4676-8BAD-68E2E451FC5B
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = MicrocodeFlashAccessLib
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
MicrocodeFlashAccessLibNull.c
[Packages]
MdePkg/MdePkg.dec
IntelSiliconPkg/IntelSiliconPkg.dec
[LibraryClasses]
BaseMemoryLib

View File

@ -1,16 +0,0 @@
// /** @file
// Microcode flash device access library.
//
// Microcode flash device access library NULL instance.
//
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Microcode flash device access library."
#string STR_MODULE_DESCRIPTION #language en-US "Microcode flash device access library NULL instance."

View File

@ -1,27 +0,0 @@
## @file
# MicrocodeCapsulePdb
#
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
#
# Uncomment the following line and update with your platform pkg name
#
# PLATFORM_NAME = <PlatformPkg>
PLATFORM_GUID = 6875FD33-602E-4EF9-9DF2-8BA7D8B7A7AF
PLATFORM_VERSION = 0.1
#
# Uncomment the following line and update with your platform pkg name
#
# FLASH_DEFINITION = <PlatformPkg>/MicrocodeCapsulePdb/MicrocodeCapsulePdb.fdf
#
# Uncomment the following line and update with your platform pkg name
#
# OUTPUT_DIRECTORY = Build/<PlatformPkg>
SUPPORTED_ARCHITECTURES = IA32|X64
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT

View File

@ -1,26 +0,0 @@
## @file
#
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[FmpPayload.FmpPayloadMicrocode1]
IMAGE_HEADER_INIT_VERSION = 0x02
IMAGE_TYPE_ID = 96d4fdcd-1502-424d-9d4c-9b12d2dcae5c # Microcode GUID (do not change it)
IMAGE_INDEX = 0x1
HARDWARE_INSTANCE = 0x0
#
# Uncomment the following line and update with path to Microcode PDB file
#
#FILE DATA = $(WORKSPACE)/<PlatformPkg>/Microcode/Microcode.pdb
[Capsule.MicrocodeCapsule]
CAPSULE_GUID = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
CAPSULE_FLAGS = PersistAcrossReset,InitiateReset
CAPSULE_HEADER_SIZE = 0x20
CAPSULE_HEADER_INIT_VERSION = 0x1
FMP_PAYLOAD = FmpPayloadMicrocode1

View File

@ -1,20 +0,0 @@
# How to generate Microcode FMP from Microcode PDB file
1) Copy directory `UefiCpuPkg/Feature/Capsule/MicrocodeUpdatePdb` to `<Your Platform Package>/MicrocodeUpdatePdb`.
2) Uncomment and update `FILE DATA` statement in `<Your Platform Package>/MicrocodeUpdatePdb/MicrocodeCapsulePdb.fdf` with path to a Microcode PDB file. The PDB file can placed in `<Your Platform Package>/MicrocodeUpdatePdb` or any other path.
`FILE DATA = <your Microcode PDB file path>`
Uncomment and update `PLATFORM_NAME`, `FLASH_DEFINITION`, `OUTPUT_DIRECTORY` section in `<Your Platform Package>/MicrocodeUpdatePdb/MicrocodeCapsulePdb.dsc` with <Your Platform Package>.
PLATFORM_NAME = <Your Platform Package>
FLASH_DEFINITION = <Your Platform Package>/MicrocodeCapsulePdb/MicrocodeCapsulePdb.fdf
OUTPUT_DIRECTORY = Build/<Your Platform Package>
3) Use EDK II build tools to generate the Microcode FMP Capsule
`build -p <Your Platform Package>/MicrocodeCapsulePdb/MicrocodeCapsulePdb.dsc`
4) The Microcode FMP Capsule is generated at `$(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/MicrocodeCapsule.Cap`

View File

@ -1,21 +0,0 @@
## @file
# Microcode text file to binary
#
# Convert text format microcode to binary format.
#
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
BASE_NAME = Microcode
FILE_GUID = ABC36AAC-2031-4422-896E-0A3B899AD0B4
COMPONENT_TYPE = Microcode
FFS_EXT = .ffs
[Sources]
#
# Uncomment the following line and update with name of Microcode TXT file
#
#Microcode.txt

View File

@ -1,33 +0,0 @@
## @file
# MicrocodeCapsuleTxt
#
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
#
# Uncomment the following line and update with your platform pkg name
#
# PLATFORM_NAME = <PlatformPkg>
PLATFORM_GUID = 6875FD33-602E-4EF9-9DF2-8BA7D8B7A7AF
PLATFORM_VERSION = 0.1
#
# Uncomment the following line and update with your platform pkg name
#
# FLASH_DEFINITION = <PlatformPkg>/MicrocodeCapsuleTxt/MicrocodeCapsuleTxt.fdf
#
# Uncomment the following line and update with your platform pkg name
#
# OUTPUT_DIRECTORY = Build/<PlatformPkg>
SUPPORTED_ARCHITECTURES = IA32|X64
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
[Components]
#
# Uncomment the following line and update with path to Microcode INF file
#
# <PlatformPkg>/MicrocodeCapsuleTxt/Microcode/Microcode.inf

View File

@ -1,26 +0,0 @@
## @file
#
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[FmpPayload.FmpPayloadMicrocode1]
IMAGE_HEADER_INIT_VERSION = 0x02
IMAGE_TYPE_ID = 96d4fdcd-1502-424d-9d4c-9b12d2dcae5c # Microcode GUID (do not change it)
IMAGE_INDEX = 0x1
HARDWARE_INSTANCE = 0x0
#
# Uncomment the following line and update with path to Microcode MCB file
#
#FILE DATA = $(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/IA32/PlatformPkg/MicrocodeCapsuleTxt/Microcode/Microcode/OUTPUT/Microcode.mcb
[Capsule.MicrocodeCapsule]
CAPSULE_GUID = 6dcbd5ed-e82d-4c44-bda1-7194199ad92a # FMP special Guid (do not change it)
CAPSULE_FLAGS = PersistAcrossReset,InitiateReset
CAPSULE_HEADER_SIZE = 0x20
CAPSULE_HEADER_INIT_VERSION = 0x1
FMP_PAYLOAD = FmpPayloadMicrocode1

View File

@ -1,33 +0,0 @@
# How to generate Microcode FMP from Microcode TXT file
1) Copy directory `UefiCpuPkg/Feature/Capsule/MicrocodeUpdateTxt` to `<Your Platform Package>/MicrocodeUpdateTxt`
2) Copy microcode TXT file to`<Your Platform Package>/MicrocodeUpdateTxt/Microcode`
3) Uncomment and update statement in `[Sources]` section of `<Your Platform Package>/MicrocodeUpdateTxt/Microcode/Microcode.inf` with name of Microcode TXT file copied in previous step.
[Sources]
<Your Microcode TXT file>
Uncomment and update `FILE DATA` statement in `<Your Platform Package>/MicrocodeUpdateTxt/MicrocodeCapsuleTxt.fdf` with path to a Microcode MCB file. The MCB file is placed in `$(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/IA32/<Your Platform Package>/MicrocodeUpdateTxt/Microcode/Microcode/OUTPUT/`.
`FILE DATA = <your Microcode MCB file path>`
Uncomment and update `PLATFORM_NAME`, `FLASH_DEFINITION`, `OUTPUT_DIRECTORY` section in `<Your Platform Package>/MicrocodeUpdateTxt/MicrocodeCapsuleTxt.dsc` with <Your Platform Package>.
PLATFORM_NAME = <Your Platform Package>
FLASH_DEFINITION = <Your Platform Package>/MicrocodeCapsuleTxt/MicrocodeCapsuleTxt.fdf
OUTPUT_DIRECTORY = Build/<Your Platform Package>
Uncomment and update statement in `Components` section of `<Your Platform Package>/MicrocodeUpdateTxt/MicrocodeCapsuleTxt.dsc` with path to a Microcode INF file.
[Components]
<Your Microcode INF file>
4) Use EDK II build tools to generate the Microcode FMP Capsule
`build -p <Your Platform Package>/MicrocodeCapsuleTxt/MicrocodeCapsuleTxt.dsc`
5) The generated Microcode FMP Capsule is found at `$(WORKSPACE)/$(OUTPUT_DIRECTORY)/$(TARGET)_$(TOOL_CHAIN_TAG)/FV/MicrocodeCapsule.Cap`

View File

@ -1,979 +0,0 @@
/** @file
Produce FMP instance for Microcode.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "MicrocodeUpdate.h"
//
// MicrocodeFmp driver private data
//
MICROCODE_FMP_PRIVATE_DATA *mMicrocodeFmpPrivate = NULL;
EFI_FIRMWARE_MANAGEMENT_PROTOCOL mFirmwareManagementProtocol = {
FmpGetImageInfo,
FmpGetImage,
FmpSetImage,
FmpCheckImage,
FmpGetPackageInfo,
FmpSetPackageInfo
};
/**
Initialize Microcode Descriptor.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
@return EFI_SUCCESS Microcode Descriptor is initialized.
**/
EFI_STATUS
InitializeMicrocodeDescriptor (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
);
/**
Returns information about the current firmware image(s) of the device.
This function allows a copy of the current firmware image to be created and saved.
The saved copy could later been used, for example, in firmware image recovery or rollback.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
On input, this is the size of the buffer allocated by the caller.
On output, it is the size of the buffer returned by the firmware
if the buffer was large enough, or the size of the buffer needed
to contain the image(s) information if the buffer was too small.
@param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
@param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
@param[out] DescriptorCount A pointer to the location in which firmware returns the number of
descriptors or firmware images within this device.
@param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
@param[out] PackageVersion A version number that represents all the firmware images in the device.
The format is vendor specific and new version must have a greater value
than the old version. If PackageVersion is not supported, the value is
0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
that package version update is in progress.
@param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
package version name. The buffer is allocated by this function with
AllocatePool(), and it is the caller's responsibility to free it with a call
to FreePool().
@retval EFI_SUCCESS The device was successfully updated with the new image.
@retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
needed to hold the image(s) information is returned in ImageInfoSize.
@retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
@retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
**/
EFI_STATUS
EFIAPI
FmpGetImageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN OUT UINTN *ImageInfoSize,
IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
OUT UINT32 *DescriptorVersion,
OUT UINT8 *DescriptorCount,
OUT UINTN *DescriptorSize,
OUT UINT32 *PackageVersion,
OUT CHAR16 **PackageVersionName
)
{
MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
UINTN Index;
MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
if(ImageInfoSize == NULL) {
return EFI_INVALID_PARAMETER;
}
if (*ImageInfoSize < sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount) {
*ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;
return EFI_BUFFER_TOO_SMALL;
}
if (ImageInfo == NULL ||
DescriptorVersion == NULL ||
DescriptorCount == NULL ||
DescriptorSize == NULL ||
PackageVersion == NULL ||
PackageVersionName == NULL) {
return EFI_INVALID_PARAMETER;
}
*ImageInfoSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount;
*DescriptorSize = sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR);
*DescriptorCount = MicrocodeFmpPrivate->DescriptorCount;
*DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
//
// supports 1 ImageInfo descriptor
//
CopyMem(&ImageInfo[0], MicrocodeFmpPrivate->ImageDescriptor, sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR) * MicrocodeFmpPrivate->DescriptorCount);
for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
if ((ImageInfo[Index].AttributesSetting & IMAGE_ATTRIBUTE_IN_USE) != 0) {
ImageInfo[Index].LastAttemptVersion = MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion;
ImageInfo[Index].LastAttemptStatus = MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus;
}
}
//
// package version
//
*PackageVersion = MicrocodeFmpPrivate->PackageVersion;
if (MicrocodeFmpPrivate->PackageVersionName != NULL) {
*PackageVersionName = AllocateCopyPool(StrSize(MicrocodeFmpPrivate->PackageVersionName), MicrocodeFmpPrivate->PackageVersionName);
}
return EFI_SUCCESS;
}
/**
Retrieves a copy of the current firmware image of the device.
This function allows a copy of the current firmware image to be created and saved.
The saved copy could later been used, for example, in firmware image recovery or rollback.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
The number is between 1 and DescriptorCount.
@param[in,out] Image Points to the buffer where the current image is copied to.
@param[in,out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
On return, points to the length of the image, in bytes.
@retval EFI_SUCCESS The device was successfully updated with the new image.
@retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
image. The current buffer size needed to hold the image is returned
in ImageSize.
@retval EFI_INVALID_PARAMETER The Image was NULL.
@retval EFI_NOT_FOUND The current image is not copied to the buffer.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpGetImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN UINT8 ImageIndex,
IN OUT VOID *Image,
IN OUT UINTN *ImageSize
)
{
MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
MICROCODE_INFO *MicrocodeInfo;
if (Image == NULL || ImageSize == NULL) {
return EFI_INVALID_PARAMETER;
}
MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || ImageSize == NULL || Image == NULL) {
return EFI_INVALID_PARAMETER;
}
MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[ImageIndex - 1];
if (*ImageSize < MicrocodeInfo->TotalSize) {
*ImageSize = MicrocodeInfo->TotalSize;
return EFI_BUFFER_TOO_SMALL;
}
*ImageSize = MicrocodeInfo->TotalSize;
CopyMem (Image, MicrocodeInfo->MicrocodeEntryPoint, MicrocodeInfo->TotalSize);
return EFI_SUCCESS;
}
/**
Updates the firmware image of the device.
This function updates the hardware with the new firmware image.
This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
If the firmware image is updatable, the function should perform the following minimal validations
before proceeding to do the firmware image update.
- Validate the image authentication if image has attribute
IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
EFI_SECURITY_VIOLATION if the validation fails.
- Validate the image is a supported image for this device. The function returns EFI_ABORTED if
the image is unsupported. The function can optionally provide more detailed information on
why the image is not a supported image.
- Validate the data from VendorCode if not null. Image validation must be performed before
VendorCode data validation. VendorCode data is ignored or considered invalid if image
validation failed. The function returns EFI_ABORTED if the data is invalid.
VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
the caller did not specify the policy or use the default policy. As an example, vendor can implement
a policy to allow an option to force a firmware image update when the abort reason is due to the new
firmware image version is older than the current firmware image version or bad image checksum.
Sensitive operations such as those wiping the entire firmware image and render the device to be
non-functional should be encoded in the image itself rather than passed with the VendorCode.
AbortReason enables vendor to have the option to provide a more detailed description of the abort
reason to the caller.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
The number is between 1 and DescriptorCount.
@param[in] Image Points to the new image.
@param[in] ImageSize Size of the new image in bytes.
@param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
Null indicates the caller did not specify the policy or use the default policy.
@param[in] Progress A function used by the driver to report the progress of the firmware update.
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
details for the aborted operation. The buffer is allocated by this function
with AllocatePool(), and it is the caller's responsibility to free it with a
call to FreePool().
@retval EFI_SUCCESS The device was successfully updated with the new image.
@retval EFI_ABORTED The operation is aborted.
@retval EFI_INVALID_PARAMETER The Image was NULL.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpSetImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN UINT8 ImageIndex,
IN CONST VOID *Image,
IN UINTN ImageSize,
IN CONST VOID *VendorCode,
IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
OUT CHAR16 **AbortReason
)
{
EFI_STATUS Status;
EFI_STATUS VarStatus;
MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate;
if (Image == NULL || AbortReason == NULL) {
return EFI_INVALID_PARAMETER;
}
MicrocodeFmpPrivate = MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(This);
*AbortReason = NULL;
if (ImageIndex == 0 || ImageIndex > MicrocodeFmpPrivate->DescriptorCount || Image == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = MicrocodeWrite(MicrocodeFmpPrivate, (VOID *)Image, ImageSize, &MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, &MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus, AbortReason);
DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, Status - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
VarStatus = gRT->SetVariable(
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
&gEfiCallerIdGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
sizeof(MicrocodeFmpPrivate->LastAttempt),
&MicrocodeFmpPrivate->LastAttempt
);
DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus));
if (!EFI_ERROR(Status)) {
InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
DumpPrivateInfo (MicrocodeFmpPrivate);
}
return Status;
}
/**
Checks if the firmware image is valid for the device.
This function allows firmware update application to validate the firmware image without
invoking the SetImage() first.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
The number is between 1 and DescriptorCount.
@param[in] Image Points to the new image.
@param[in] ImageSize Size of the new image in bytes.
@param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
if available, additional information if the image is invalid.
@retval EFI_SUCCESS The image was successfully checked.
@retval EFI_INVALID_PARAMETER The Image was NULL.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpCheckImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN UINT8 ImageIndex,
IN CONST VOID *Image,
IN UINTN ImageSize,
OUT UINT32 *ImageUpdatable
)
{
return EFI_UNSUPPORTED;
}
/**
Returns information about the firmware package.
This function returns package information.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[out] PackageVersion A version number that represents all the firmware images in the device.
The format is vendor specific and new version must have a greater value
than the old version. If PackageVersion is not supported, the value is
0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
comparison is to be performed using PackageVersionName. A value of
0xFFFFFFFD indicates that package version update is in progress.
@param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
the package version name. The buffer is allocated by this function with
AllocatePool(), and it is the caller's responsibility to free it with a
call to FreePool().
@param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
package version name. A value of 0 indicates the device does not support
update of package version name. Length is the number of Unicode characters,
including the terminating null character.
@param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
Definitions' for possible returned values of this parameter. A value of 1
indicates the attribute is supported and the current setting value is
indicated in AttributesSetting. A value of 0 indicates the attribute is not
supported and the current setting value in AttributesSetting is meaningless.
@param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
values of this parameter
@retval EFI_SUCCESS The package information was successfully returned.
@retval EFI_UNSUPPORTED The operation is not supported.
**/
EFI_STATUS
EFIAPI
FmpGetPackageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
OUT UINT32 *PackageVersion,
OUT CHAR16 **PackageVersionName,
OUT UINT32 *PackageVersionNameMaxLen,
OUT UINT64 *AttributesSupported,
OUT UINT64 *AttributesSetting
)
{
return EFI_UNSUPPORTED;
}
/**
Updates information about the firmware package.
This function updates package information.
This function returns EFI_UNSUPPORTED if the package information is not updatable.
VendorCode enables vendor to implement vendor-specific package information update policy.
Null if the caller did not specify this policy or use the default policy.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] Image Points to the authentication image.
Null if authentication is not required.
@param[in] ImageSize Size of the authentication image in bytes.
0 if authentication is not required.
@param[in] VendorCode This enables vendor to implement vendor-specific firmware
image update policy.
Null indicates the caller did not specify this policy or use
the default policy.
@param[in] PackageVersion The new package version.
@param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
the package version name.
The string length is equal to or less than the value returned in
PackageVersionNameMaxLen.
@retval EFI_SUCCESS The device was successfully updated with the new package
information.
@retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
returned in PackageVersionNameMaxLen.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpSetPackageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN CONST VOID *Image,
IN UINTN ImageSize,
IN CONST VOID *VendorCode,
IN UINT32 PackageVersion,
IN CONST CHAR16 *PackageVersionName
)
{
return EFI_UNSUPPORTED;
}
/**
Sort FIT microcode entries based upon MicrocodeEntryPoint, from low to high.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
**/
VOID
SortFitMicrocodeInfo (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
FIT_MICROCODE_INFO *FitMicrocodeEntry;
FIT_MICROCODE_INFO *NextFitMicrocodeEntry;
FIT_MICROCODE_INFO TempFitMicrocodeEntry;
FIT_MICROCODE_INFO *FitMicrocodeEntryEnd;
FitMicrocodeEntry = MicrocodeFmpPrivate->FitMicrocodeInfo;
NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
FitMicrocodeEntryEnd = MicrocodeFmpPrivate->FitMicrocodeInfo + MicrocodeFmpPrivate->FitMicrocodeEntryCount;
while (FitMicrocodeEntry < FitMicrocodeEntryEnd) {
while (NextFitMicrocodeEntry < FitMicrocodeEntryEnd) {
if (FitMicrocodeEntry->MicrocodeEntryPoint > NextFitMicrocodeEntry->MicrocodeEntryPoint) {
CopyMem (&TempFitMicrocodeEntry, FitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));
CopyMem (FitMicrocodeEntry, NextFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));
CopyMem (NextFitMicrocodeEntry, &TempFitMicrocodeEntry, sizeof (FIT_MICROCODE_INFO));
}
NextFitMicrocodeEntry = NextFitMicrocodeEntry + 1;
}
FitMicrocodeEntry = FitMicrocodeEntry + 1;
NextFitMicrocodeEntry = FitMicrocodeEntry + 1;
}
}
/**
Initialize FIT microcode information.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
@return EFI_SUCCESS FIT microcode information is initialized.
@return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
@return EFI_DEVICE_ERROR There is something wrong in FIT microcode entry.
**/
EFI_STATUS
InitializeFitMicrocodeInfo (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
UINT64 FitPointer;
FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
UINT32 EntryNum;
UINT32 MicrocodeEntryNum;
UINT32 Index;
UINTN Address;
VOID *MicrocodePatchAddress;
UINTN MicrocodePatchRegionSize;
FIT_MICROCODE_INFO *FitMicrocodeInfo;
FIT_MICROCODE_INFO *FitMicrocodeInfoNext;
CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
CPU_MICROCODE_HEADER *MicrocodeEntryPointNext;
UINTN FitMicrocodeIndex;
MICROCODE_INFO *MicrocodeInfo;
UINTN MicrocodeIndex;
if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
}
FitPointer = *(UINT64 *) (UINTN) FIT_POINTER_ADDRESS;
if ((FitPointer == 0) ||
(FitPointer == 0xFFFFFFFFFFFFFFFF) ||
(FitPointer == 0xEEEEEEEEEEEEEEEE)) {
//
// No FIT table.
//
return EFI_SUCCESS;
}
FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *) (UINTN) FitPointer;
if ((FitEntry[0].Type != FIT_TYPE_00_HEADER) ||
(FitEntry[0].Address != FIT_TYPE_00_SIGNATURE)) {
//
// Invalid FIT table, treat it as no FIT table.
//
return EFI_SUCCESS;
}
EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
//
// Calculate microcode entry number.
//
MicrocodeEntryNum = 0;
for (Index = 0; Index < EntryNum; Index++) {
if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
MicrocodeEntryNum++;
}
}
if (MicrocodeEntryNum == 0) {
//
// No FIT microcode entry.
//
return EFI_SUCCESS;
}
//
// Allocate buffer.
//
MicrocodeFmpPrivate->FitMicrocodeInfo = AllocateZeroPool (MicrocodeEntryNum * sizeof (FIT_MICROCODE_INFO));
if (MicrocodeFmpPrivate->FitMicrocodeInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
MicrocodeFmpPrivate->FitMicrocodeEntryCount = MicrocodeEntryNum;
MicrocodePatchAddress = MicrocodeFmpPrivate->MicrocodePatchAddress;
MicrocodePatchRegionSize = MicrocodeFmpPrivate->MicrocodePatchRegionSize;
//
// Collect microcode entry info.
//
MicrocodeEntryNum = 0;
for (Index = 0; Index < EntryNum; Index++) {
if (FitEntry[Index].Type == FIT_TYPE_01_MICROCODE) {
Address = (UINTN) FitEntry[Index].Address;
if ((Address < (UINTN) MicrocodePatchAddress) ||
(Address >= ((UINTN) MicrocodePatchAddress + MicrocodePatchRegionSize))) {
DEBUG ((
DEBUG_ERROR,
"InitializeFitMicrocodeInfo - Address (0x%x) is not in Microcode Region\n",
Address
));
goto ErrorExit;
}
FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[MicrocodeEntryNum];
FitMicrocodeInfo->MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) Address;
if ((*(UINT32 *) Address) == 0xFFFFFFFF) {
//
// It is the empty slot as long as the first dword is 0xFFFF_FFFF.
//
FitMicrocodeInfo->Empty = TRUE;
} else {
FitMicrocodeInfo->Empty = FALSE;
}
MicrocodeEntryNum++;
}
}
//
// Every microcode should have a FIT microcode entry.
//
for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {
MicrocodeInfo = &MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex];
for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount; FitMicrocodeIndex++) {
FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
if (MicrocodeInfo->MicrocodeEntryPoint == FitMicrocodeInfo->MicrocodeEntryPoint) {
FitMicrocodeInfo->TotalSize = MicrocodeInfo->TotalSize;
FitMicrocodeInfo->InUse = MicrocodeInfo->InUse;
break;
}
}
if (FitMicrocodeIndex >= MicrocodeFmpPrivate->FitMicrocodeEntryCount) {
DEBUG ((
DEBUG_ERROR,
"InitializeFitMicrocodeInfo - There is no FIT microcode entry for Microcode (0x%x)\n",
MicrocodeInfo->MicrocodeEntryPoint
));
goto ErrorExit;
}
}
SortFitMicrocodeInfo (MicrocodeFmpPrivate);
//
// Check overlap.
//
for (FitMicrocodeIndex = 0; FitMicrocodeIndex < MicrocodeFmpPrivate->FitMicrocodeEntryCount - 1; FitMicrocodeIndex++) {
FitMicrocodeInfo = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex];
MicrocodeEntryPoint = FitMicrocodeInfo->MicrocodeEntryPoint;
FitMicrocodeInfoNext = &MicrocodeFmpPrivate->FitMicrocodeInfo[FitMicrocodeIndex + 1];
MicrocodeEntryPointNext = FitMicrocodeInfoNext->MicrocodeEntryPoint;
if ((MicrocodeEntryPoint >= MicrocodeEntryPointNext) ||
((FitMicrocodeInfo->TotalSize != 0) &&
((UINTN) MicrocodeEntryPoint + FitMicrocodeInfo->TotalSize) >
(UINTN) MicrocodeEntryPointNext)) {
DEBUG ((
DEBUG_ERROR,
"InitializeFitMicrocodeInfo - There is overlap between FIT microcode entries (0x%x 0x%x)\n",
MicrocodeEntryPoint,
MicrocodeEntryPointNext
));
goto ErrorExit;
}
}
return EFI_SUCCESS;
ErrorExit:
FreePool (MicrocodeFmpPrivate->FitMicrocodeInfo);
MicrocodeFmpPrivate->FitMicrocodeInfo = NULL;
MicrocodeFmpPrivate->FitMicrocodeEntryCount = 0;
return EFI_DEVICE_ERROR;
}
/**
Initialize Processor Microcode Index.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
**/
VOID
InitializedProcessorMicrocodeIndex (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
UINTN CpuIndex;
UINTN MicrocodeIndex;
UINTN TargetCpuIndex;
UINT32 AttemptStatus;
EFI_STATUS Status;
for (CpuIndex = 0; CpuIndex < MicrocodeFmpPrivate->ProcessorCount; CpuIndex++) {
if (MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex != (UINTN)-1) {
continue;
}
for (MicrocodeIndex = 0; MicrocodeIndex < MicrocodeFmpPrivate->DescriptorCount; MicrocodeIndex++) {
if (!MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].InUse) {
continue;
}
TargetCpuIndex = CpuIndex;
Status = VerifyMicrocode(
MicrocodeFmpPrivate,
MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].MicrocodeEntryPoint,
MicrocodeFmpPrivate->MicrocodeInfo[MicrocodeIndex].TotalSize,
FALSE,
&AttemptStatus,
NULL,
&TargetCpuIndex
);
if (!EFI_ERROR(Status)) {
MicrocodeFmpPrivate->ProcessorInfo[CpuIndex].MicrocodeIndex = MicrocodeIndex;
}
}
}
}
/**
Initialize Microcode Descriptor.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
@return EFI_SUCCESS Microcode Descriptor is initialized.
@return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
**/
EFI_STATUS
InitializeMicrocodeDescriptor (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
EFI_STATUS Status;
UINT8 CurrentMicrocodeCount;
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, 0, NULL, NULL);
if (CurrentMicrocodeCount > MicrocodeFmpPrivate->DescriptorCount) {
if (MicrocodeFmpPrivate->ImageDescriptor != NULL) {
FreePool(MicrocodeFmpPrivate->ImageDescriptor);
MicrocodeFmpPrivate->ImageDescriptor = NULL;
}
if (MicrocodeFmpPrivate->MicrocodeInfo != NULL) {
FreePool(MicrocodeFmpPrivate->MicrocodeInfo);
MicrocodeFmpPrivate->MicrocodeInfo = NULL;
}
} else {
ZeroMem(MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));
ZeroMem(MicrocodeFmpPrivate->MicrocodeInfo, MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));
}
MicrocodeFmpPrivate->DescriptorCount = CurrentMicrocodeCount;
if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {
MicrocodeFmpPrivate->ImageDescriptor = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR));
if (MicrocodeFmpPrivate->ImageDescriptor == NULL) {
return EFI_OUT_OF_RESOURCES;
}
}
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
MicrocodeFmpPrivate->MicrocodeInfo = AllocateZeroPool(MicrocodeFmpPrivate->DescriptorCount * sizeof(MICROCODE_INFO));
if (MicrocodeFmpPrivate->MicrocodeInfo == NULL) {
FreePool (MicrocodeFmpPrivate->ImageDescriptor);
return EFI_OUT_OF_RESOURCES;
}
}
CurrentMicrocodeCount = (UINT8)GetMicrocodeInfo (MicrocodeFmpPrivate, MicrocodeFmpPrivate->DescriptorCount, MicrocodeFmpPrivate->ImageDescriptor, MicrocodeFmpPrivate->MicrocodeInfo);
ASSERT(CurrentMicrocodeCount == MicrocodeFmpPrivate->DescriptorCount);
InitializedProcessorMicrocodeIndex (MicrocodeFmpPrivate);
Status = InitializeFitMicrocodeInfo (MicrocodeFmpPrivate);
if (EFI_ERROR(Status)) {
FreePool (MicrocodeFmpPrivate->ImageDescriptor);
FreePool (MicrocodeFmpPrivate->MicrocodeInfo);
DEBUG((DEBUG_ERROR, "InitializeFitMicrocodeInfo - %r\n", Status));
return Status;
}
return EFI_SUCCESS;
}
/**
Initialize MicrocodeFmpDriver multiprocessor information.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
@return EFI_SUCCESS Processor information is initialized.
@return EFI_OUT_OF_RESOURCES No enough resource for the initialization.
**/
EFI_STATUS
InitializeProcessorInfo (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
EFI_STATUS Status;
EFI_MP_SERVICES_PROTOCOL *MpService;
UINTN NumberOfProcessors;
UINTN NumberOfEnabledProcessors;
UINTN Index;
UINTN BspIndex;
Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);
ASSERT_EFI_ERROR(Status);
MicrocodeFmpPrivate->MpService = MpService;
MicrocodeFmpPrivate->ProcessorCount = 0;
MicrocodeFmpPrivate->ProcessorInfo = NULL;
Status = MpService->GetNumberOfProcessors (MpService, &NumberOfProcessors, &NumberOfEnabledProcessors);
ASSERT_EFI_ERROR(Status);
MicrocodeFmpPrivate->ProcessorCount = NumberOfProcessors;
Status = MpService->WhoAmI (MpService, &BspIndex);
ASSERT_EFI_ERROR(Status);
MicrocodeFmpPrivate->BspIndex = BspIndex;
MicrocodeFmpPrivate->ProcessorInfo = AllocateZeroPool (sizeof(PROCESSOR_INFO) * MicrocodeFmpPrivate->ProcessorCount);
if (MicrocodeFmpPrivate->ProcessorInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
for (Index = 0; Index < NumberOfProcessors; Index++) {
MicrocodeFmpPrivate->ProcessorInfo[Index].CpuIndex = Index;
MicrocodeFmpPrivate->ProcessorInfo[Index].MicrocodeIndex = (UINTN)-1;
if (Index == BspIndex) {
CollectProcessorInfo (&MicrocodeFmpPrivate->ProcessorInfo[Index]);
} else {
Status = MpService->StartupThisAP (
MpService,
CollectProcessorInfo,
Index,
NULL,
0,
&MicrocodeFmpPrivate->ProcessorInfo[Index],
NULL
);
ASSERT_EFI_ERROR(Status);
}
}
return EFI_SUCCESS;
}
/**
Dump private information.
@param[in] MicrocodeFmpPrivate private data structure.
**/
VOID
DumpPrivateInfo (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
UINTN Index;
PROCESSOR_INFO *ProcessorInfo;
MICROCODE_INFO *MicrocodeInfo;
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
FIT_MICROCODE_INFO *FitMicrocodeInfo;
DEBUG ((DEBUG_INFO, "ProcessorInfo:\n"));
DEBUG ((DEBUG_INFO, " ProcessorCount - 0x%x\n", MicrocodeFmpPrivate->ProcessorCount));
DEBUG ((DEBUG_INFO, " BspIndex - 0x%x\n", MicrocodeFmpPrivate->BspIndex));
ProcessorInfo = MicrocodeFmpPrivate->ProcessorInfo;
for (Index = 0; Index < MicrocodeFmpPrivate->ProcessorCount; Index++) {
DEBUG ((
DEBUG_INFO,
" ProcessorInfo[0x%x] - 0x%08x, 0x%02x, 0x%08x, (0x%x)\n",
ProcessorInfo[Index].CpuIndex,
ProcessorInfo[Index].ProcessorSignature,
ProcessorInfo[Index].PlatformId,
ProcessorInfo[Index].MicrocodeRevision,
ProcessorInfo[Index].MicrocodeIndex
));
}
DEBUG ((DEBUG_INFO, "MicrocodeInfo:\n"));
MicrocodeInfo = MicrocodeFmpPrivate->MicrocodeInfo;
DEBUG ((DEBUG_INFO, " MicrocodeRegion - 0x%x - 0x%x\n", MicrocodeFmpPrivate->MicrocodePatchAddress, MicrocodeFmpPrivate->MicrocodePatchRegionSize));
DEBUG ((DEBUG_INFO, " MicrocodeCount - 0x%x\n", MicrocodeFmpPrivate->DescriptorCount));
for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
DEBUG ((
DEBUG_INFO,
" MicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x)\n",
Index,
MicrocodeInfo[Index].MicrocodeEntryPoint,
MicrocodeInfo[Index].TotalSize,
MicrocodeInfo[Index].InUse
));
}
ImageDescriptor = MicrocodeFmpPrivate->ImageDescriptor;
DEBUG ((DEBUG_VERBOSE, "ImageDescriptor:\n"));
for (Index = 0; Index < MicrocodeFmpPrivate->DescriptorCount; Index++) {
DEBUG((DEBUG_VERBOSE, " ImageDescriptor (%d)\n", Index));
DEBUG((DEBUG_VERBOSE, " ImageIndex - 0x%x\n", ImageDescriptor[Index].ImageIndex));
DEBUG((DEBUG_VERBOSE, " ImageTypeId - %g\n", &ImageDescriptor[Index].ImageTypeId));
DEBUG((DEBUG_VERBOSE, " ImageId - 0x%lx\n", ImageDescriptor[Index].ImageId));
DEBUG((DEBUG_VERBOSE, " ImageIdName - %s\n", ImageDescriptor[Index].ImageIdName));
DEBUG((DEBUG_VERBOSE, " Version - 0x%x\n", ImageDescriptor[Index].Version));
DEBUG((DEBUG_VERBOSE, " VersionName - %s\n", ImageDescriptor[Index].VersionName));
DEBUG((DEBUG_VERBOSE, " Size - 0x%x\n", ImageDescriptor[Index].Size));
DEBUG((DEBUG_VERBOSE, " AttributesSupported - 0x%lx\n", ImageDescriptor[Index].AttributesSupported));
DEBUG((DEBUG_VERBOSE, " AttributesSetting - 0x%lx\n", ImageDescriptor[Index].AttributesSetting));
DEBUG((DEBUG_VERBOSE, " Compatibilities - 0x%lx\n", ImageDescriptor[Index].Compatibilities));
DEBUG((DEBUG_VERBOSE, " LowestSupportedImageVersion - 0x%x\n", ImageDescriptor[Index].LowestSupportedImageVersion));
DEBUG((DEBUG_VERBOSE, " LastAttemptVersion - 0x%x\n", ImageDescriptor[Index].LastAttemptVersion));
DEBUG((DEBUG_VERBOSE, " LastAttemptStatus - 0x%x\n", ImageDescriptor[Index].LastAttemptStatus));
DEBUG((DEBUG_VERBOSE, " HardwareInstance - 0x%lx\n", ImageDescriptor[Index].HardwareInstance));
}
if (MicrocodeFmpPrivate->FitMicrocodeInfo != NULL) {
DEBUG ((DEBUG_INFO, "FitMicrocodeInfo:\n"));
FitMicrocodeInfo = MicrocodeFmpPrivate->FitMicrocodeInfo;
DEBUG ((DEBUG_INFO, " FitMicrocodeEntryCount - 0x%x\n", MicrocodeFmpPrivate->FitMicrocodeEntryCount));
for (Index = 0; Index < MicrocodeFmpPrivate->FitMicrocodeEntryCount; Index++) {
DEBUG ((
DEBUG_INFO,
" FitMicrocodeInfo[0x%x] - 0x%08x, 0x%08x, (0x%x, 0x%x)\n",
Index,
FitMicrocodeInfo[Index].MicrocodeEntryPoint,
FitMicrocodeInfo[Index].TotalSize,
FitMicrocodeInfo[Index].InUse,
FitMicrocodeInfo[Index].Empty
));
}
}
}
/**
Initialize MicrocodeFmpDriver private data structure.
@param[in] MicrocodeFmpPrivate private data structure to be initialized.
@return EFI_SUCCESS private data is initialized.
**/
EFI_STATUS
InitializePrivateData (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
)
{
EFI_STATUS Status;
EFI_STATUS VarStatus;
UINTN VarSize;
BOOLEAN Result;
MicrocodeFmpPrivate->Signature = MICROCODE_FMP_PRIVATE_DATA_SIGNATURE;
MicrocodeFmpPrivate->Handle = NULL;
CopyMem(&MicrocodeFmpPrivate->Fmp, &mFirmwareManagementProtocol, sizeof(EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
MicrocodeFmpPrivate->PackageVersion = 0x1;
MicrocodeFmpPrivate->PackageVersionName = L"Microcode";
MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion = 0x0;
MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus = 0x0;
VarSize = sizeof(MicrocodeFmpPrivate->LastAttempt);
VarStatus = gRT->GetVariable(
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME,
&gEfiCallerIdGuid,
NULL,
&VarSize,
&MicrocodeFmpPrivate->LastAttempt
);
DEBUG((DEBUG_INFO, "GetLastAttempt - %r\n", VarStatus));
DEBUG((DEBUG_INFO, "GetLastAttempt Version - 0x%x, State - 0x%x\n", MicrocodeFmpPrivate->LastAttempt.LastAttemptVersion, MicrocodeFmpPrivate->LastAttempt.LastAttemptStatus));
Result = GetMicrocodeRegion(&MicrocodeFmpPrivate->MicrocodePatchAddress, &MicrocodeFmpPrivate->MicrocodePatchRegionSize);
if (!Result) {
DEBUG((DEBUG_ERROR, "Fail to get Microcode Region\n"));
return EFI_NOT_FOUND;
}
Status = InitializeProcessorInfo (MicrocodeFmpPrivate);
if (EFI_ERROR(Status)) {
DEBUG((DEBUG_ERROR, "InitializeProcessorInfo - %r\n", Status));
return Status;
}
Status = InitializeMicrocodeDescriptor(MicrocodeFmpPrivate);
if (EFI_ERROR(Status)) {
FreePool (MicrocodeFmpPrivate->ProcessorInfo);
DEBUG((DEBUG_ERROR, "InitializeMicrocodeDescriptor - %r\n", Status));
return Status;
}
DumpPrivateInfo (MicrocodeFmpPrivate);
return Status;
}
/**
Microcode FMP module entrypoint
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@return EFI_SUCCESS Microcode FMP module is initialized.
**/
EFI_STATUS
EFIAPI
MicrocodeFmpMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
//
// Initialize MicrocodeFmpPrivateData
//
mMicrocodeFmpPrivate = AllocateZeroPool (sizeof(MICROCODE_FMP_PRIVATE_DATA));
if (mMicrocodeFmpPrivate == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = InitializePrivateData(mMicrocodeFmpPrivate);
if (EFI_ERROR(Status)) {
FreePool(mMicrocodeFmpPrivate);
mMicrocodeFmpPrivate = NULL;
return Status;
}
//
// Install FMP protocol.
//
Status = gBS->InstallProtocolInterface (
&mMicrocodeFmpPrivate->Handle,
&gEfiFirmwareManagementProtocolGuid,
EFI_NATIVE_INTERFACE,
&mMicrocodeFmpPrivate->Fmp
);
if (EFI_ERROR (Status)) {
FreePool(mMicrocodeFmpPrivate);
mMicrocodeFmpPrivate = NULL;
return Status;
}
return Status;
}

View File

@ -1,499 +0,0 @@
/** @file
Microcode update header file.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _MICROCODE_FMP_H_
#define _MICROCODE_FMP_H_
#include <PiDxe.h>
#include <Guid/SystemResourceTable.h>
#include <Guid/MicrocodeFmp.h>
#include <IndustryStandard/FirmwareInterfaceTable.h>
#include <Protocol/FirmwareManagement.h>
#include <Protocol/MpService.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/DevicePathLib.h>
#include <Library/HobLib.h>
#include <Library/MicrocodeFlashAccessLib.h>
#include <Register/Cpuid.h>
#include <Register/Msr.h>
#include <Register/Microcode.h>
#define MICROCODE_FMP_PRIVATE_DATA_SIGNATURE SIGNATURE_32('M', 'C', 'U', 'F')
//
// Microcode FMP private data structure.
//
typedef struct {
UINT32 LastAttemptVersion;
UINT32 LastAttemptStatus;
} MICROCODE_FMP_LAST_ATTEMPT_VARIABLE;
typedef struct {
CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
UINTN TotalSize;
BOOLEAN InUse;
} MICROCODE_INFO;
typedef struct {
CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
UINTN TotalSize;
BOOLEAN InUse;
BOOLEAN Empty;
} FIT_MICROCODE_INFO;
typedef struct {
UINTN CpuIndex;
UINT32 ProcessorSignature;
UINT8 PlatformId;
UINT32 MicrocodeRevision;
UINTN MicrocodeIndex;
} PROCESSOR_INFO;
typedef struct {
UINT64 Address;
UINT32 Revision;
} MICROCODE_LOAD_BUFFER;
struct _MICROCODE_FMP_PRIVATE_DATA {
UINT32 Signature;
EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp;
EFI_HANDLE Handle;
VOID *MicrocodePatchAddress;
UINTN MicrocodePatchRegionSize;
UINT8 DescriptorCount;
EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor;
MICROCODE_INFO *MicrocodeInfo;
UINT32 PackageVersion;
CHAR16 *PackageVersionName;
MICROCODE_FMP_LAST_ATTEMPT_VARIABLE LastAttempt;
EFI_MP_SERVICES_PROTOCOL *MpService;
UINTN BspIndex;
UINTN ProcessorCount;
PROCESSOR_INFO *ProcessorInfo;
UINT32 FitMicrocodeEntryCount;
FIT_MICROCODE_INFO *FitMicrocodeInfo;
};
typedef struct _MICROCODE_FMP_PRIVATE_DATA MICROCODE_FMP_PRIVATE_DATA;
#define MICROCODE_FMP_LAST_ATTEMPT_VARIABLE_NAME L"MicrocodeLastAttemptVar"
/**
Returns a pointer to the MICROCODE_FMP_PRIVATE_DATA structure from the input a as Fmp.
If the signatures matches, then a pointer to the data structure that contains
a specified field of that data structure is returned.
@param a Pointer to the field specified by ServiceBinding within
a data structure of type MICROCODE_FMP_PRIVATE_DATA.
**/
#define MICROCODE_FMP_PRIVATE_DATA_FROM_FMP(a) \
CR ( \
(a), \
MICROCODE_FMP_PRIVATE_DATA, \
Fmp, \
MICROCODE_FMP_PRIVATE_DATA_SIGNATURE \
)
/**
Get Microcode Region.
@param[out] MicrocodePatchAddress The address of Microcode
@param[out] MicrocodePatchRegionSize The region size of Microcode
@retval TRUE The Microcode region is returned.
@retval FALSE No Microcode region.
**/
BOOLEAN
GetMicrocodeRegion (
OUT VOID **MicrocodePatchAddress,
OUT UINTN *MicrocodePatchRegionSize
);
/**
Collect processor information.
The function prototype for invoking a function on an Application Processor.
@param[in,out] Buffer The pointer to private data buffer.
**/
VOID
EFIAPI
CollectProcessorInfo (
IN OUT VOID *Buffer
);
/**
Get current Microcode information.
The ProcessorInformation (BspIndex/ProcessorCount/ProcessorInfo)
in MicrocodeFmpPrivate must be initialized.
The MicrocodeInformation (DescriptorCount/ImageDescriptor/MicrocodeInfo)
in MicrocodeFmpPrivate may not be avaiable in this function.
@param[in] MicrocodeFmpPrivate The Microcode driver private data
@param[in] DescriptorCount The count of Microcode ImageDescriptor allocated.
@param[out] ImageDescriptor Microcode ImageDescriptor
@param[out] MicrocodeInfo Microcode information
@return Microcode count
**/
UINTN
GetMicrocodeInfo (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
IN UINTN DescriptorCount, OPTIONAL
OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageDescriptor, OPTIONAL
OUT MICROCODE_INFO *MicrocodeInfo OPTIONAL
);
/**
Verify Microcode.
Caution: This function may receive untrusted input.
@param[in] MicrocodeFmpPrivate The Microcode driver private data
@param[in] Image The Microcode image buffer.
@param[in] ImageSize The size of Microcode image buffer in bytes.
@param[in] TryLoad Try to load Microcode or not.
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
details for the aborted operation. The buffer is allocated by this function
with AllocatePool(), and it is the caller's responsibility to free it with a
call to FreePool().
@param[in, out] TargetCpuIndex On input, the index of target CPU which tries to match the Microcode. (UINTN)-1 means to try all.
On output, the index of target CPU which matches the Microcode.
@retval EFI_SUCCESS The Microcode image passes verification.
@retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt.
@retval EFI_INCOMPATIBLE_VERSION The Microcode image version is incorrect.
@retval EFI_UNSUPPORTED The Microcode ProcessorSignature or ProcessorFlags is incorrect.
@retval EFI_SECURITY_VIOLATION The Microcode image fails to load.
**/
EFI_STATUS
VerifyMicrocode (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
IN VOID *Image,
IN UINTN ImageSize,
IN BOOLEAN TryLoad,
OUT UINT32 *LastAttemptStatus,
OUT CHAR16 **AbortReason, OPTIONAL
IN OUT UINTN *TargetCpuIndex OPTIONAL
);
/**
Write Microcode.
@param[in] MicrocodeFmpPrivate The Microcode driver private data
@param[in] Image The Microcode image buffer.
@param[in] ImageSize The size of Microcode image buffer in bytes.
@param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
details for the aborted operation. The buffer is allocated by this function
with AllocatePool(), and it is the caller's responsibility to free it with a
call to FreePool().
@retval EFI_SUCCESS The Microcode image is written.
@retval EFI_VOLUME_CORRUPTED The Microcode image is corrupt.
@retval EFI_INCOMPATIBLE_VERSION The Microcode image version is incorrect.
@retval EFI_SECURITY_VIOLATION The Microcode image fails to load.
@retval EFI_WRITE_PROTECTED The flash device is read only.
**/
EFI_STATUS
MicrocodeWrite (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate,
IN VOID *Image,
IN UINTN ImageSize,
OUT UINT32 *LastAttemptVersion,
OUT UINT32 *LastAttemptStatus,
OUT CHAR16 **AbortReason
);
/**
Dump private information.
@param[in] MicrocodeFmpPrivate private data structure.
**/
VOID
DumpPrivateInfo (
IN MICROCODE_FMP_PRIVATE_DATA *MicrocodeFmpPrivate
);
/**
Returns information about the current firmware image(s) of the device.
This function allows a copy of the current firmware image to be created and saved.
The saved copy could later been used, for example, in firmware image recovery or rollback.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
On input, this is the size of the buffer allocated by the caller.
On output, it is the size of the buffer returned by the firmware
if the buffer was large enough, or the size of the buffer needed
to contain the image(s) information if the buffer was too small.
@param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
@param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
@param[out] DescriptorCount A pointer to the location in which firmware returns the number of
descriptors or firmware images within this device.
@param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
@param[out] PackageVersion A version number that represents all the firmware images in the device.
The format is vendor specific and new version must have a greater value
than the old version. If PackageVersion is not supported, the value is
0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
that package version update is in progress.
@param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
package version name. The buffer is allocated by this function with
AllocatePool(), and it is the caller's responsibility to free it with a call
to FreePool().
@retval EFI_SUCCESS The device was successfully updated with the new image.
@retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
needed to hold the image(s) information is returned in ImageInfoSize.
@retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
@retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
**/
EFI_STATUS
EFIAPI
FmpGetImageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN OUT UINTN *ImageInfoSize,
IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
OUT UINT32 *DescriptorVersion,
OUT UINT8 *DescriptorCount,
OUT UINTN *DescriptorSize,
OUT UINT32 *PackageVersion,
OUT CHAR16 **PackageVersionName
);
/**
Retrieves a copy of the current firmware image of the device.
This function allows a copy of the current firmware image to be created and saved.
The saved copy could later been used, for example, in firmware image recovery or rollback.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
The number is between 1 and DescriptorCount.
@param[in,out] Image Points to the buffer where the current image is copied to.
@param[in,out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
On return, points to the length of the image, in bytes.
@retval EFI_SUCCESS The device was successfully updated with the new image.
@retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
image. The current buffer size needed to hold the image is returned
in ImageSize.
@retval EFI_INVALID_PARAMETER The Image was NULL.
@retval EFI_NOT_FOUND The current image is not copied to the buffer.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpGetImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN UINT8 ImageIndex,
IN OUT VOID *Image,
IN OUT UINTN *ImageSize
);
/**
Updates the firmware image of the device.
This function updates the hardware with the new firmware image.
This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
If the firmware image is updatable, the function should perform the following minimal validations
before proceeding to do the firmware image update.
- Validate the image authentication if image has attribute
IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
EFI_SECURITY_VIOLATION if the validation fails.
- Validate the image is a supported image for this device. The function returns EFI_ABORTED if
the image is unsupported. The function can optionally provide more detailed information on
why the image is not a supported image.
- Validate the data from VendorCode if not null. Image validation must be performed before
VendorCode data validation. VendorCode data is ignored or considered invalid if image
validation failed. The function returns EFI_ABORTED if the data is invalid.
VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
the caller did not specify the policy or use the default policy. As an example, vendor can implement
a policy to allow an option to force a firmware image update when the abort reason is due to the new
firmware image version is older than the current firmware image version or bad image checksum.
Sensitive operations such as those wiping the entire firmware image and render the device to be
non-functional should be encoded in the image itself rather than passed with the VendorCode.
AbortReason enables vendor to have the option to provide a more detailed description of the abort
reason to the caller.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
The number is between 1 and DescriptorCount.
@param[in] Image Points to the new image.
@param[in] ImageSize Size of the new image in bytes.
@param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
Null indicates the caller did not specify the policy or use the default policy.
@param[in] Progress A function used by the driver to report the progress of the firmware update.
@param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
details for the aborted operation. The buffer is allocated by this function
with AllocatePool(), and it is the caller's responsibility to free it with a
call to FreePool().
@retval EFI_SUCCESS The device was successfully updated with the new image.
@retval EFI_ABORTED The operation is aborted.
@retval EFI_INVALID_PARAMETER The Image was NULL.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpSetImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN UINT8 ImageIndex,
IN CONST VOID *Image,
IN UINTN ImageSize,
IN CONST VOID *VendorCode,
IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
OUT CHAR16 **AbortReason
);
/**
Checks if the firmware image is valid for the device.
This function allows firmware update application to validate the firmware image without
invoking the SetImage() first.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
The number is between 1 and DescriptorCount.
@param[in] Image Points to the new image.
@param[in] ImageSize Size of the new image in bytes.
@param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
if available, additional information if the image is invalid.
@retval EFI_SUCCESS The image was successfully checked.
@retval EFI_INVALID_PARAMETER The Image was NULL.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpCheckImage (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN UINT8 ImageIndex,
IN CONST VOID *Image,
IN UINTN ImageSize,
OUT UINT32 *ImageUpdatable
);
/**
Returns information about the firmware package.
This function returns package information.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[out] PackageVersion A version number that represents all the firmware images in the device.
The format is vendor specific and new version must have a greater value
than the old version. If PackageVersion is not supported, the value is
0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
comparison is to be performed using PackageVersionName. A value of
0xFFFFFFFD indicates that package version update is in progress.
@param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
the package version name. The buffer is allocated by this function with
AllocatePool(), and it is the caller's responsibility to free it with a
call to FreePool().
@param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
package version name. A value of 0 indicates the device does not support
update of package version name. Length is the number of Unicode characters,
including the terminating null character.
@param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
Definitions' for possible returned values of this parameter. A value of 1
indicates the attribute is supported and the current setting value is
indicated in AttributesSetting. A value of 0 indicates the attribute is not
supported and the current setting value in AttributesSetting is meaningless.
@param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
values of this parameter
@retval EFI_SUCCESS The package information was successfully returned.
@retval EFI_UNSUPPORTED The operation is not supported.
**/
EFI_STATUS
EFIAPI
FmpGetPackageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
OUT UINT32 *PackageVersion,
OUT CHAR16 **PackageVersionName,
OUT UINT32 *PackageVersionNameMaxLen,
OUT UINT64 *AttributesSupported,
OUT UINT64 *AttributesSetting
);
/**
Updates information about the firmware package.
This function updates package information.
This function returns EFI_UNSUPPORTED if the package information is not updatable.
VendorCode enables vendor to implement vendor-specific package information update policy.
Null if the caller did not specify this policy or use the default policy.
@param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
@param[in] Image Points to the authentication image.
Null if authentication is not required.
@param[in] ImageSize Size of the authentication image in bytes.
0 if authentication is not required.
@param[in] VendorCode This enables vendor to implement vendor-specific firmware
image update policy.
Null indicates the caller did not specify this policy or use
the default policy.
@param[in] PackageVersion The new package version.
@param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
the package version name.
The string length is equal to or less than the value returned in
PackageVersionNameMaxLen.
@retval EFI_SUCCESS The device was successfully updated with the new package
information.
@retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
returned in PackageVersionNameMaxLen.
@retval EFI_UNSUPPORTED The operation is not supported.
@retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
**/
EFI_STATUS
EFIAPI
FmpSetPackageInfo (
IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
IN CONST VOID *Image,
IN UINTN ImageSize,
IN CONST VOID *VendorCode,
IN UINT32 PackageVersion,
IN CONST CHAR16 *PackageVersionName
);
#endif

View File

@ -1,67 +0,0 @@
## @file
# Microcode FMP update driver.
#
# Produce FMP instance to update Microcode.
#
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = MicrocodeUpdateDxe
MODULE_UNI_FILE = MicrocodeUpdateDxe.uni
FILE_GUID = 0565365C-2FE1-4F88-B3BE-624C04623A20
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = MicrocodeFmpMain
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = X64
#
[Sources]
MicrocodeUpdate.h
MicrocodeFmp.c
MicrocodeUpdate.c
[Packages]
MdePkg/MdePkg.dec
IntelSiliconPkg/IntelSiliconPkg.dec
UefiCpuPkg/UefiCpuPkg.dec
[LibraryClasses]
BaseLib
UefiLib
BaseMemoryLib
DebugLib
PcdLib
MemoryAllocationLib
UefiBootServicesTableLib
HobLib
UefiRuntimeServicesTableLib
UefiDriverEntryPoint
MicrocodeFlashAccessLib
[Guids]
gMicrocodeFmpImageTypeIdGuid ## CONSUMES ## GUID
[Protocols]
gEfiFirmwareManagementProtocolGuid ## PRODUCES
gEfiMpServiceProtocolGuid ## CONSUMES
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchAddress ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
[Depex]
gEfiVariableArchProtocolGuid AND
gEfiVariableWriteArchProtocolGuid AND
gEfiMpServiceProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
MicrocodeUpdateDxeExtra.uni

View File

@ -1,15 +0,0 @@
// /** @file
// Microcode FMP update driver.
//
// Produce FMP instance to update Microcode.
//
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Microcode FMP update driver."
#string STR_MODULE_DESCRIPTION #language en-US "Produce FMP instance to update Microcode."

View File

@ -1,14 +0,0 @@
// /** @file
// MicrocodeUpdateDxe Localized Strings and Content
//
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_PROPERTIES_MODULE_NAME
#language en-US
"MicrocodeUpdate DXE Driver"

View File

@ -1,538 +0,0 @@
/** @file
BmDma related function
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DmaProtection.h"
// TBD: May make it a policy
#define DMA_MEMORY_TOP MAX_UINTN
//#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL
#define MAP_HANDLE_INFO_SIGNATURE SIGNATURE_32 ('H', 'M', 'A', 'P')
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
EFI_HANDLE DeviceHandle;
UINT64 IoMmuAccess;
} MAP_HANDLE_INFO;
#define MAP_HANDLE_INFO_FROM_LINK(a) CR (a, MAP_HANDLE_INFO, Link, MAP_HANDLE_INFO_SIGNATURE)
#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
EDKII_IOMMU_OPERATION Operation;
UINTN NumberOfBytes;
UINTN NumberOfPages;
EFI_PHYSICAL_ADDRESS HostAddress;
EFI_PHYSICAL_ADDRESS DeviceAddress;
LIST_ENTRY HandleList;
} MAP_INFO;
#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)
LIST_ENTRY gMaps = INITIALIZE_LIST_HEAD_VARIABLE(gMaps);
/**
This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,
based upon the DeviceAddress.
@param[in] DeviceHandle The device who initiates the DMA access request.
@param[in] DeviceAddress The base of device memory address to be used as the DMA memory.
@param[in] Length The length of device memory address to be used as the DMA memory.
@param[in] IoMmuAccess The IOMMU access.
**/
VOID
SyncDeviceHandleToMapInfo (
IN EFI_HANDLE DeviceHandle,
IN EFI_PHYSICAL_ADDRESS DeviceAddress,
IN UINT64 Length,
IN UINT64 IoMmuAccess
)
{
MAP_INFO *MapInfo;
MAP_HANDLE_INFO *MapHandleInfo;
LIST_ENTRY *Link;
EFI_TPL OriginalTpl;
//
// Find MapInfo according to DeviceAddress
//
OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);
MapInfo = NULL;
for (Link = GetFirstNode (&gMaps)
; !IsNull (&gMaps, Link)
; Link = GetNextNode (&gMaps, Link)
) {
MapInfo = MAP_INFO_FROM_LINK (Link);
if (MapInfo->DeviceAddress == DeviceAddress) {
break;
}
}
if ((MapInfo == NULL) || (MapInfo->DeviceAddress != DeviceAddress)) {
DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: DeviceAddress(0x%lx) - not found\n", DeviceAddress));
gBS->RestoreTPL (OriginalTpl);
return ;
}
//
// Find MapHandleInfo according to DeviceHandle
//
MapHandleInfo = NULL;
for (Link = GetFirstNode (&MapInfo->HandleList)
; !IsNull (&MapInfo->HandleList, Link)
; Link = GetNextNode (&MapInfo->HandleList, Link)
) {
MapHandleInfo = MAP_HANDLE_INFO_FROM_LINK (Link);
if (MapHandleInfo->DeviceHandle == DeviceHandle) {
break;
}
}
if ((MapHandleInfo != NULL) && (MapHandleInfo->DeviceHandle == DeviceHandle)) {
MapHandleInfo->IoMmuAccess = IoMmuAccess;
gBS->RestoreTPL (OriginalTpl);
return ;
}
//
// No DeviceHandle
// Initialize and insert the MAP_HANDLE_INFO structure
//
MapHandleInfo = AllocatePool (sizeof (MAP_HANDLE_INFO));
if (MapHandleInfo == NULL) {
DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: %r\n", EFI_OUT_OF_RESOURCES));
gBS->RestoreTPL (OriginalTpl);
return ;
}
MapHandleInfo->Signature = MAP_HANDLE_INFO_SIGNATURE;
MapHandleInfo->DeviceHandle = DeviceHandle;
MapHandleInfo->IoMmuAccess = IoMmuAccess;
InsertTailList (&MapInfo->HandleList, &MapHandleInfo->Link);
gBS->RestoreTPL (OriginalTpl);
return ;
}
/**
Provides the controller-specific addresses required to access system memory from a
DMA bus master.
@param This The protocol 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().
@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.
**/
EFI_STATUS
EFIAPI
IoMmuMap (
IN EDKII_IOMMU_PROTOCOL *This,
IN EDKII_IOMMU_OPERATION Operation,
IN VOID *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS PhysicalAddress;
MAP_INFO *MapInfo;
EFI_PHYSICAL_ADDRESS DmaMemoryTop;
BOOLEAN NeedRemap;
EFI_TPL OriginalTpl;
if (NumberOfBytes == NULL || DeviceAddress == NULL ||
Mapping == NULL) {
DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));
return EFI_INVALID_PARAMETER;
}
DEBUG ((DEBUG_VERBOSE, "IoMmuMap: ==> 0x%08x - 0x%08x (%x)\n", HostAddress, *NumberOfBytes, Operation));
//
// Make sure that Operation is valid
//
if ((UINT32) Operation >= EdkiiIoMmuOperationMaximum) {
DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));
return EFI_INVALID_PARAMETER;
}
NeedRemap = FALSE;
PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
DmaMemoryTop = DMA_MEMORY_TOP;
//
// Alignment check
//
if ((*NumberOfBytes != ALIGN_VALUE(*NumberOfBytes, SIZE_4KB)) ||
(PhysicalAddress != ALIGN_VALUE(PhysicalAddress, SIZE_4KB))) {
if ((Operation == EdkiiIoMmuOperationBusMasterCommonBuffer) ||
(Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64)) {
//
// The input buffer might be a subset from IoMmuAllocateBuffer.
// Skip the check.
//
} else {
NeedRemap = TRUE;
}
}
if ((PhysicalAddress + *NumberOfBytes) >= DMA_MEMORY_TOP) {
NeedRemap = TRUE;
}
if (((Operation != EdkiiIoMmuOperationBusMasterRead64 &&
Operation != EdkiiIoMmuOperationBusMasterWrite64 &&
Operation != EdkiiIoMmuOperationBusMasterCommonBuffer64)) &&
((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {
//
// If the root bridge or the device cannot handle performing DMA above
// 4GB but any part of the DMA transfer being mapped is above 4GB, then
// map the DMA transfer to a buffer below 4GB.
//
NeedRemap = TRUE;
DmaMemoryTop = MIN (DmaMemoryTop, SIZE_4GB - 1);
}
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
if (NeedRemap) {
//
// Common Buffer operations can not be remapped. If the common buffer
// is above 4GB, then it is not possible to generate a mapping, so return
// an error.
//
DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_UNSUPPORTED));
return EFI_UNSUPPORTED;
}
}
//
// Allocate a MAP_INFO structure to remember the mapping when Unmap() is
// called later.
//
MapInfo = AllocatePool (sizeof (MAP_INFO));
if (MapInfo == NULL) {
*NumberOfBytes = 0;
DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_OUT_OF_RESOURCES));
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize the MAP_INFO structure
//
MapInfo->Signature = MAP_INFO_SIGNATURE;
MapInfo->Operation = Operation;
MapInfo->NumberOfBytes = *NumberOfBytes;
MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
MapInfo->HostAddress = PhysicalAddress;
MapInfo->DeviceAddress = DmaMemoryTop;
InitializeListHead(&MapInfo->HandleList);
//
// Allocate a buffer below 4GB to map the transfer to.
//
if (NeedRemap) {
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiBootServicesData,
MapInfo->NumberOfPages,
&MapInfo->DeviceAddress
);
if (EFI_ERROR (Status)) {
FreePool (MapInfo);
*NumberOfBytes = 0;
DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", Status));
return Status;
}
//
// If this is a read operation from the Bus Master's point of view,
// then copy the contents of the real buffer into the mapped buffer
// so the Bus Master can read the contents of the real buffer.
//
if (Operation == EdkiiIoMmuOperationBusMasterRead ||
Operation == EdkiiIoMmuOperationBusMasterRead64) {
CopyMem (
(VOID *) (UINTN) MapInfo->DeviceAddress,
(VOID *) (UINTN) MapInfo->HostAddress,
MapInfo->NumberOfBytes
);
}
} else {
MapInfo->DeviceAddress = MapInfo->HostAddress;
}
OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);
InsertTailList (&gMaps, &MapInfo->Link);
gBS->RestoreTPL (OriginalTpl);
//
// The DeviceAddress is the address of the maped buffer below 4GB
//
*DeviceAddress = MapInfo->DeviceAddress;
//
// Return a pointer to the MAP_INFO structure in Mapping
//
*Mapping = MapInfo;
DEBUG ((DEBUG_VERBOSE, "IoMmuMap: 0x%08x - 0x%08x <==\n", *DeviceAddress, *Mapping));
return EFI_SUCCESS;
}
/**
Completes the Map() operation and releases any corresponding resources.
@param This The protocol instance pointer.
@param 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.
**/
EFI_STATUS
EFIAPI
IoMmuUnmap (
IN EDKII_IOMMU_PROTOCOL *This,
IN VOID *Mapping
)
{
MAP_INFO *MapInfo;
MAP_HANDLE_INFO *MapHandleInfo;
LIST_ENTRY *Link;
EFI_TPL OriginalTpl;
DEBUG ((DEBUG_VERBOSE, "IoMmuUnmap: 0x%08x\n", Mapping));
if (Mapping == NULL) {
DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));
return EFI_INVALID_PARAMETER;
}
OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);
MapInfo = NULL;
for (Link = GetFirstNode (&gMaps)
; !IsNull (&gMaps, Link)
; Link = GetNextNode (&gMaps, Link)
) {
MapInfo = MAP_INFO_FROM_LINK (Link);
if (MapInfo == Mapping) {
break;
}
}
//
// Mapping is not a valid value returned by Map()
//
if (MapInfo != Mapping) {
gBS->RestoreTPL (OriginalTpl);
DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));
return EFI_INVALID_PARAMETER;
}
RemoveEntryList (&MapInfo->Link);
gBS->RestoreTPL (OriginalTpl);
//
// remove all nodes in MapInfo->HandleList
//
while (!IsListEmpty (&MapInfo->HandleList)) {
MapHandleInfo = MAP_HANDLE_INFO_FROM_LINK (MapInfo->HandleList.ForwardLink);
RemoveEntryList (&MapHandleInfo->Link);
FreePool (MapHandleInfo);
}
if (MapInfo->DeviceAddress != MapInfo->HostAddress) {
//
// If this is a write operation from the Bus Master's point of view,
// then copy the contents of the mapped buffer into the real buffer
// so the processor can read the contents of the real buffer.
//
if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
CopyMem (
(VOID *) (UINTN) MapInfo->HostAddress,
(VOID *) (UINTN) MapInfo->DeviceAddress,
MapInfo->NumberOfBytes
);
}
//
// Free the mapped buffer and the MAP_INFO structure.
//
gBS->FreePages (MapInfo->DeviceAddress, MapInfo->NumberOfPages);
}
FreePool (Mapping);
return EFI_SUCCESS;
}
/**
Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
OperationBusMasterCommonBuffer64 mapping.
@param This The protocol instance pointer.
@param Type This parameter is not used and must be ignored.
@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.
@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.
**/
EFI_STATUS
EFIAPI
IoMmuAllocateBuffer (
IN EDKII_IOMMU_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT VOID **HostAddress,
IN UINT64 Attributes
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS PhysicalAddress;
DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: ==> 0x%08x\n", Pages));
//
// Validate Attributes
//
if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_UNSUPPORTED));
return EFI_UNSUPPORTED;
}
//
// Check for invalid inputs
//
if (HostAddress == NULL) {
DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETER));
return EFI_INVALID_PARAMETER;
}
//
// The only valid memory types are EfiBootServicesData and
// EfiRuntimeServicesData
//
if (MemoryType != EfiBootServicesData &&
MemoryType != EfiRuntimeServicesData) {
DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETER));
return EFI_INVALID_PARAMETER;
}
PhysicalAddress = DMA_MEMORY_TOP;
if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
//
// Limit allocations to memory below 4GB
//
PhysicalAddress = MIN (PhysicalAddress, SIZE_4GB - 1);
}
Status = gBS->AllocatePages (
AllocateMaxAddress,
MemoryType,
Pages,
&PhysicalAddress
);
if (!EFI_ERROR (Status)) {
*HostAddress = (VOID *) (UINTN) PhysicalAddress;
}
DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: 0x%08x <==\n", *HostAddress));
return Status;
}
/**
Frees memory that was allocated with AllocateBuffer().
@param This The protocol instance pointer.
@param Pages The number of pages to free.
@param 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().
**/
EFI_STATUS
EFIAPI
IoMmuFreeBuffer (
IN EDKII_IOMMU_PROTOCOL *This,
IN UINTN Pages,
IN VOID *HostAddress
)
{
DEBUG ((DEBUG_VERBOSE, "IoMmuFreeBuffer: 0x%\n", Pages));
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
}
/**
Get device information from mapping.
@param[in] Mapping The mapping.
@param[out] DeviceAddress The device address of the mapping.
@param[out] NumberOfPages The number of pages of the mapping.
@retval EFI_SUCCESS The device information is returned.
@retval EFI_INVALID_PARAMETER The mapping is invalid.
**/
EFI_STATUS
GetDeviceInfoFromMapping (
IN VOID *Mapping,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT UINTN *NumberOfPages
)
{
MAP_INFO *MapInfo;
LIST_ENTRY *Link;
if (Mapping == NULL) {
return EFI_INVALID_PARAMETER;
}
MapInfo = NULL;
for (Link = GetFirstNode (&gMaps)
; !IsNull (&gMaps, Link)
; Link = GetNextNode (&gMaps, Link)
) {
MapInfo = MAP_INFO_FROM_LINK (Link);
if (MapInfo == Mapping) {
break;
}
}
//
// Mapping is not a valid value returned by Map()
//
if (MapInfo != Mapping) {
return EFI_INVALID_PARAMETER;
}
*DeviceAddress = MapInfo->DeviceAddress;
*NumberOfPages = MapInfo->NumberOfPages;
return EFI_SUCCESS;
}

View File

@ -1,683 +0,0 @@
/** @file
Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DmaProtection.h"
UINT64 mBelow4GMemoryLimit;
UINT64 mAbove4GMemoryLimit;
EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;
VTD_ACCESS_REQUEST *mAccessRequest = NULL;
UINTN mAccessRequestCount = 0;
UINTN mAccessRequestMaxCount = 0;
/**
Append VTd Access Request to global.
@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] BaseAddress The base of device memory address to be used as the DMA memory.
@param[in] Length The length of device memory address to be used as the DMA memory.
@param[in] IoMmuAccess The IOMMU access.
@retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
@retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is 0.
@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 BaseAddress and Length.
@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.
**/
EFI_STATUS
RequestAccessAttribute (
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId,
IN UINT64 BaseAddress,
IN UINT64 Length,
IN UINT64 IoMmuAccess
)
{
VTD_ACCESS_REQUEST *NewAccessRequest;
UINTN Index;
//
// Optimization for memory.
//
// If the last record is to IoMmuAccess=0,
// Check previous records and remove the matched entry.
//
if (IoMmuAccess == 0) {
for (Index = 0; Index < mAccessRequestCount; Index++) {
if ((mAccessRequest[Index].Segment == Segment) &&
(mAccessRequest[Index].SourceId.Uint16 == SourceId.Uint16) &&
(mAccessRequest[Index].BaseAddress == BaseAddress) &&
(mAccessRequest[Index].Length == Length) &&
(mAccessRequest[Index].IoMmuAccess != 0)) {
//
// Remove this record [Index].
// No need to add the new record.
//
if (Index != mAccessRequestCount - 1) {
CopyMem (
&mAccessRequest[Index],
&mAccessRequest[Index + 1],
sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index)
);
}
ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCESS_REQUEST));
mAccessRequestCount--;
return EFI_SUCCESS;
}
}
}
if (mAccessRequestCount >= mAccessRequestMaxCount) {
NewAccessRequest = AllocateZeroPool (sizeof(*NewAccessRequest) * (mAccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));
if (NewAccessRequest == NULL) {
return EFI_OUT_OF_RESOURCES;
}
mAccessRequestMaxCount += MAX_VTD_ACCESS_REQUEST;
if (mAccessRequest != NULL) {
CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest) * mAccessRequestCount);
FreePool (mAccessRequest);
}
mAccessRequest = NewAccessRequest;
}
ASSERT (mAccessRequestCount < mAccessRequestMaxCount);
mAccessRequest[mAccessRequestCount].Segment = Segment;
mAccessRequest[mAccessRequestCount].SourceId = SourceId;
mAccessRequest[mAccessRequestCount].BaseAddress = BaseAddress;
mAccessRequest[mAccessRequestCount].Length = Length;
mAccessRequest[mAccessRequestCount].IoMmuAccess = IoMmuAccess;
mAccessRequestCount++;
return EFI_SUCCESS;
}
/**
Process Access Requests from before DMAR table is installed.
**/
VOID
ProcessRequestedAccessAttribute (
VOID
)
{
UINTN Index;
EFI_STATUS Status;
DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));
for (Index = 0; Index < mAccessRequestCount; Index++) {
DEBUG ((
DEBUG_INFO,
"PCI(S%x.B%x.D%x.F%x) ",
mAccessRequest[Index].Segment,
mAccessRequest[Index].SourceId.Bits.Bus,
mAccessRequest[Index].SourceId.Bits.Device,
mAccessRequest[Index].SourceId.Bits.Function
));
DEBUG ((
DEBUG_INFO,
"(0x%lx~0x%lx) - %lx\n",
mAccessRequest[Index].BaseAddress,
mAccessRequest[Index].Length,
mAccessRequest[Index].IoMmuAccess
));
Status = SetAccessAttribute (
mAccessRequest[Index].Segment,
mAccessRequest[Index].SourceId,
mAccessRequest[Index].BaseAddress,
mAccessRequest[Index].Length,
mAccessRequest[Index].IoMmuAccess
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));
}
}
if (mAccessRequest != NULL) {
FreePool (mAccessRequest);
}
mAccessRequest = NULL;
mAccessRequestCount = 0;
mAccessRequestMaxCount = 0;
DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));
}
/**
return the UEFI memory information.
@param[out] Below4GMemoryLimit The below 4GiB memory limit
@param[out] Above4GMemoryLimit The above 4GiB memory limit
**/
VOID
ReturnUefiMemoryMap (
OUT UINT64 *Below4GMemoryLimit,
OUT UINT64 *Above4GMemoryLimit
)
{
EFI_STATUS Status;
EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;
EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;
EFI_MEMORY_DESCRIPTOR *EfiEntry;
EFI_MEMORY_DESCRIPTOR *NextEfiEntry;
EFI_MEMORY_DESCRIPTOR TempEfiEntry;
UINTN EfiMemoryMapSize;
UINTN EfiMapKey;
UINTN EfiDescriptorSize;
UINT32 EfiDescriptorVersion;
UINT64 MemoryBlockLength;
*Below4GMemoryLimit = 0;
*Above4GMemoryLimit = 0;
//
// Get the EFI memory map.
//
EfiMemoryMapSize = 0;
EfiMemoryMap = NULL;
Status = gBS->GetMemoryMap (
&EfiMemoryMapSize,
EfiMemoryMap,
&EfiMapKey,
&EfiDescriptorSize,
&EfiDescriptorVersion
);
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
do {
//
// Use size returned back plus 1 descriptor for the AllocatePool.
// We don't just multiply by 2 since the "for" loop below terminates on
// EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize
// we process bogus entries and create bogus E820 entries.
//
EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize);
ASSERT (EfiMemoryMap != NULL);
Status = gBS->GetMemoryMap (
&EfiMemoryMapSize,
EfiMemoryMap,
&EfiMapKey,
&EfiDescriptorSize,
&EfiDescriptorVersion
);
if (EFI_ERROR (Status)) {
FreePool (EfiMemoryMap);
}
} while (Status == EFI_BUFFER_TOO_SMALL);
ASSERT_EFI_ERROR (Status);
//
// Sort memory map from low to high
//
EfiEntry = EfiMemoryMap;
NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
while (EfiEntry < EfiMemoryMapEnd) {
while (NextEfiEntry < EfiMemoryMapEnd) {
if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {
CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
}
NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize);
}
EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
}
//
//
//
DEBUG ((DEBUG_INFO, "MemoryMap:\n"));
EfiEntry = EfiMemoryMap;
EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
while (EfiEntry < EfiMemoryMapEnd) {
MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12));
DEBUG ((DEBUG_INFO, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry->Type, EfiEntry->PhysicalStart, EfiEntry->PhysicalStart + MemoryBlockLength));
switch (EfiEntry->Type) {
case EfiLoaderCode:
case EfiLoaderData:
case EfiBootServicesCode:
case EfiBootServicesData:
case EfiConventionalMemory:
case EfiRuntimeServicesCode:
case EfiRuntimeServicesData:
case EfiACPIReclaimMemory:
case EfiACPIMemoryNVS:
case EfiReservedMemoryType:
if ((EfiEntry->PhysicalStart + MemoryBlockLength) <= BASE_1MB) {
//
// Skip the memory block is under 1MB
//
} else if (EfiEntry->PhysicalStart >= BASE_4GB) {
if (*Above4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLength) {
*Above4GMemoryLimit = EfiEntry->PhysicalStart + MemoryBlockLength;
}
} else {
if (*Below4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLength) {
*Below4GMemoryLimit = EfiEntry->PhysicalStart + MemoryBlockLength;
}
}
break;
}
EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
}
FreePool (EfiMemoryMap);
DEBUG ((DEBUG_INFO, "Result:\n"));
DEBUG ((DEBUG_INFO, "Below4GMemoryLimit: 0x%016lx\n", *Below4GMemoryLimit));
DEBUG ((DEBUG_INFO, "Above4GMemoryLimit: 0x%016lx\n", *Above4GMemoryLimit));
return ;
}
/**
The scan bus callback function to always enable page attribute.
@param[in] Context The context of the callback.
@param[in] Segment The segment of the source.
@param[in] Bus The bus of the source.
@param[in] Device The device of the source.
@param[in] Function The function of the source.
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
**/
EFI_STATUS
EFIAPI
ScanBusCallbackAlwaysEnablePageAttribute (
IN VOID *Context,
IN UINT16 Segment,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Function
)
{
VTD_SOURCE_ID SourceId;
EFI_STATUS Status;
SourceId.Bits.Bus = Bus;
SourceId.Bits.Device = Device;
SourceId.Bits.Function = Function;
Status = AlwaysEnablePageAttribute (Segment, SourceId);
return Status;
}
/**
Always enable the VTd page attribute for the device in the DeviceScope.
@param[in] DeviceScope the input device scope data structure
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device in the device scope.
**/
EFI_STATUS
AlwaysEnablePageAttributeDeviceScope (
IN EDKII_PLATFORM_VTD_DEVICE_SCOPE *DeviceScope
)
{
UINT8 Bus;
UINT8 Device;
UINT8 Function;
VTD_SOURCE_ID SourceId;
UINT8 SecondaryBusNumber;
EFI_STATUS Status;
Status = GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceScope->DeviceScope, &Bus, &Device, &Function);
if (DeviceScope->DeviceScope.Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE) {
//
// Need scan the bridge and add all devices.
//
SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DeviceScope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
Status = ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusNumber, ScanBusCallbackAlwaysEnablePageAttribute);
return Status;
} else {
SourceId.Bits.Bus = Bus;
SourceId.Bits.Device = Device;
SourceId.Bits.Function = Function;
Status = AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, SourceId);
return Status;
}
}
/**
Always enable the VTd page attribute for the device matching DeviceId.
@param[in] PciDeviceId the input PCI device ID
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device matching DeviceId.
**/
EFI_STATUS
AlwaysEnablePageAttributePciDeviceId (
IN EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId
)
{
UINTN VtdIndex;
UINTN PciIndex;
PCI_DEVICE_DATA *PciDeviceData;
EFI_STATUS Status;
for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {
for (PciIndex = 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; PciIndex++) {
PciDeviceData = &mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[PciIndex];
if (((PciDeviceId->VendorId == 0xFFFF) || (PciDeviceId->VendorId == PciDeviceData->PciDeviceId.VendorId)) &&
((PciDeviceId->DeviceId == 0xFFFF) || (PciDeviceId->DeviceId == PciDeviceData->PciDeviceId.DeviceId)) &&
((PciDeviceId->RevisionId == 0xFF) || (PciDeviceId->RevisionId == PciDeviceData->PciDeviceId.RevisionId)) &&
((PciDeviceId->SubsystemVendorId == 0xFFFF) || (PciDeviceId->SubsystemVendorId == PciDeviceData->PciDeviceId.SubsystemVendorId)) &&
((PciDeviceId->SubsystemDeviceId == 0xFFFF) || (PciDeviceId->SubsystemDeviceId == PciDeviceData->PciDeviceId.SubsystemDeviceId)) ) {
Status = AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex].Segment, PciDeviceData->PciSourceId);
if (EFI_ERROR(Status)) {
continue;
}
}
}
}
return EFI_SUCCESS;
}
/**
Always enable the VTd page attribute for the device.
@param[in] DeviceInfo the exception device information
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device in the device info.
**/
EFI_STATUS
AlwaysEnablePageAttributeExceptionDeviceInfo (
IN EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *DeviceInfo
)
{
switch (DeviceInfo->Type) {
case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:
return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1));
case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:
return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1));
default:
return EFI_UNSUPPORTED;
}
}
/**
Initialize platform VTd policy.
**/
VOID
InitializePlatformVTdPolicy (
VOID
)
{
EFI_STATUS Status;
UINTN DeviceInfoCount;
VOID *DeviceInfo;
EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;
UINTN Index;
//
// It is optional.
//
Status = gBS->LocateProtocol (
&gEdkiiPlatformVTdPolicyProtocolGuid,
NULL,
(VOID **)&mPlatformVTdPolicy
);
if (!EFI_ERROR(Status)) {
DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));
Status = mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPolicy, &DeviceInfoCount, &DeviceInfo);
if (!EFI_ERROR(Status)) {
ThisDeviceInfo = DeviceInfo;
for (Index = 0; Index < DeviceInfoCount; Index++) {
if (ThisDeviceInfo->Type == EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_END) {
break;
}
AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);
ThisDeviceInfo = (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo->Length);
}
FreePool (DeviceInfo);
}
}
}
/**
Setup VTd engine.
**/
VOID
SetupVtd (
VOID
)
{
EFI_STATUS Status;
VOID *PciEnumerationComplete;
UINTN Index;
UINT64 Below4GMemoryLimit;
UINT64 Above4GMemoryLimit;
//
// PCI Enumeration must be done
//
Status = gBS->LocateProtocol (
&gEfiPciEnumerationCompleteProtocolGuid,
NULL,
&PciEnumerationComplete
);
ASSERT_EFI_ERROR (Status);
ReturnUefiMemoryMap (&Below4GMemoryLimit, &Above4GMemoryLimit);
Below4GMemoryLimit = ALIGN_VALUE_UP(Below4GMemoryLimit, SIZE_256MB);
DEBUG ((DEBUG_INFO, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GMemoryLimit));
mBelow4GMemoryLimit = Below4GMemoryLimit;
mAbove4GMemoryLimit = Above4GMemoryLimit;
//
// 1. setup
//
DEBUG ((DEBUG_INFO, "ParseDmarAcpiTable\n"));
Status = ParseDmarAcpiTableDrhd ();
if (EFI_ERROR (Status)) {
return;
}
DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));
PrepareVtdConfig ();
//
// 2. initialization
//
DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));
Status = SetupTranslationTable ();
if (EFI_ERROR (Status)) {
return;
}
InitializePlatformVTdPolicy ();
ParseDmarAcpiTableRmrr ();
if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) == 0) {
//
// Support IOMMU access attribute request recording before DMAR table is installed.
// Here is to process the requests.
//
ProcessRequestedAccessAttribute ();
}
for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment));
if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
DumpDmarExtContextEntryTable (mVtdUnitInformation[Index].ExtRootEntryTable);
}
if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
DumpDmarContextEntryTable (mVtdUnitInformation[Index].RootEntryTable);
}
}
//
// 3. enable
//
DEBUG ((DEBUG_INFO, "EnableDmar\n"));
Status = EnableDmar ();
if (EFI_ERROR (Status)) {
return;
}
DEBUG ((DEBUG_INFO, "DumpVtdRegs\n"));
DumpVtdRegsAll ();
}
/**
Notification function of ACPI Table change.
This is a notification function registered on ACPI Table change event.
@param Event Event whose notification function is being invoked.
@param Context Pointer to the notification function's context.
**/
VOID
EFIAPI
AcpiNotificationFunc (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
Status = GetDmarAcpiTable ();
if (EFI_ERROR (Status)) {
if (Status == EFI_ALREADY_STARTED) {
gBS->CloseEvent (Event);
}
return;
}
SetupVtd ();
gBS->CloseEvent (Event);
}
/**
Exit boot service callback function.
@param[in] Event The event handle.
@param[in] Context The event content.
**/
VOID
EFIAPI
OnExitBootServices (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINTN VtdIndex;
DEBUG ((DEBUG_INFO, "Vtd OnExitBootServices\n"));
DumpVtdRegsAll ();
DEBUG ((DEBUG_INFO, "Invalidate all\n"));
for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {
FlushWriteBuffer (VtdIndex);
InvalidateContextCache (VtdIndex);
InvalidateIOTLB (VtdIndex);
}
if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
DisableDmar ();
DumpVtdRegsAll ();
}
}
/**
Legacy boot callback function.
@param[in] Event The event handle.
@param[in] Context The event content.
**/
VOID
EFIAPI
OnLegacyBoot (
EFI_EVENT Event,
VOID *Context
)
{
DEBUG ((DEBUG_INFO, "Vtd OnLegacyBoot\n"));
DumpVtdRegsAll ();
DisableDmar ();
DumpVtdRegsAll ();
}
/**
Initialize DMA protection.
**/
VOID
InitializeDmaProtection (
VOID
)
{
EFI_STATUS Status;
EFI_EVENT ExitBootServicesEvent;
EFI_EVENT LegacyBootEvent;
EFI_EVENT EventAcpi10;
EFI_EVENT EventAcpi20;
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
VTD_TPL_LEVEL,
AcpiNotificationFunc,
NULL,
&gEfiAcpi10TableGuid,
&EventAcpi10
);
ASSERT_EFI_ERROR (Status);
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
VTD_TPL_LEVEL,
AcpiNotificationFunc,
NULL,
&gEfiAcpi20TableGuid,
&EventAcpi20
);
ASSERT_EFI_ERROR (Status);
//
// Signal the events initially for the case
// that DMAR table has been installed.
//
gBS->SignalEvent (EventAcpi20);
gBS->SignalEvent (EventAcpi10);
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_CALLBACK,
OnExitBootServices,
NULL,
&gEfiEventExitBootServicesGuid,
&ExitBootServicesEvent
);
ASSERT_EFI_ERROR (Status);
Status = EfiCreateEventLegacyBootEx (
TPL_CALLBACK,
OnLegacyBoot,
NULL,
&LegacyBootEvent
);
ASSERT_EFI_ERROR (Status);
return ;
}

View File

@ -1,632 +0,0 @@
/** @file
Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _DMAR_PROTECTION_H_
#define _DMAR_PROTECTION_H_
#include <Uefi.h>
#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/IoLib.h>
#include <Library/PciSegmentLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/CacheMaintenanceLib.h>
#include <Library/PerformanceLib.h>
#include <Library/PrintLib.h>
#include <Library/ReportStatusCodeLib.h>
#include <Guid/EventGroup.h>
#include <Guid/Acpi.h>
#include <Protocol/DxeSmmReadyToLock.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Protocol/PciIo.h>
#include <Protocol/PciEnumerationComplete.h>
#include <Protocol/PlatformVtdPolicy.h>
#include <Protocol/IoMmu.h>
#include <IndustryStandard/Pci.h>
#include <IndustryStandard/DmaRemappingReportingTable.h>
#include <IndustryStandard/Vtd.h>
#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32))
#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (~((Alignment) - 1)))
#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))
#define VTD_TPL_LEVEL TPL_NOTIFY
//
// This is the initial max PCI DATA number.
// The number may be enlarged later.
//
#define MAX_VTD_PCI_DATA_NUMBER 0x100
typedef struct {
UINT8 DeviceType;
VTD_SOURCE_ID PciSourceId;
EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId;
// for statistic analysis
UINTN AccessCount;
} PCI_DEVICE_DATA;
typedef struct {
BOOLEAN IncludeAllFlag;
UINTN PciDeviceDataNumber;
UINTN PciDeviceDataMaxNumber;
PCI_DEVICE_DATA *PciDeviceData;
} PCI_DEVICE_INFORMATION;
typedef struct {
UINTN VtdUnitBaseAddress;
UINT16 Segment;
VTD_CAP_REG CapReg;
VTD_ECAP_REG ECapReg;
VTD_ROOT_ENTRY *RootEntryTable;
VTD_EXT_ROOT_ENTRY *ExtRootEntryTable;
VTD_SECOND_LEVEL_PAGING_ENTRY *FixedSecondLevelPagingEntry;
BOOLEAN HasDirtyContext;
BOOLEAN HasDirtyPages;
PCI_DEVICE_INFORMATION PciDeviceInfo;
} VTD_UNIT_INFORMATION;
//
// This is the initial max ACCESS request.
// The number may be enlarged later.
//
#define MAX_VTD_ACCESS_REQUEST 0x100
typedef struct {
UINT16 Segment;
VTD_SOURCE_ID SourceId;
UINT64 BaseAddress;
UINT64 Length;
UINT64 IoMmuAccess;
} VTD_ACCESS_REQUEST;
/**
The scan bus callback function.
It is called in PCI bus scan for each PCI device under the bus.
@param[in] Context The context of the callback.
@param[in] Segment The segment of the source.
@param[in] Bus The bus of the source.
@param[in] Device The device of the source.
@param[in] Function The function of the source.
@retval EFI_SUCCESS The specific PCI device is processed in the callback.
**/
typedef
EFI_STATUS
(EFIAPI *SCAN_BUS_FUNC_CALLBACK_FUNC) (
IN VOID *Context,
IN UINT16 Segment,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Function
);
extern EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;
extern UINTN mVtdUnitNumber;
extern VTD_UNIT_INFORMATION *mVtdUnitInformation;
extern UINT64 mBelow4GMemoryLimit;
extern UINT64 mAbove4GMemoryLimit;
extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;
/**
Prepare VTD configuration.
**/
VOID
PrepareVtdConfig (
VOID
);
/**
Setup VTd translation table.
@retval EFI_SUCCESS Setup translation table successfully.
@retval EFI_OUT_OF_RESOURCE Setup translation table fail.
**/
EFI_STATUS
SetupTranslationTable (
VOID
);
/**
Enable DMAR translation.
@retval EFI_SUCCESS DMAR translation is enabled.
@retval EFI_DEVICE_ERROR DMAR translation is not enabled.
**/
EFI_STATUS
EnableDmar (
VOID
);
/**
Disable DMAR translation.
@retval EFI_SUCCESS DMAR translation is disabled.
@retval EFI_DEVICE_ERROR DMAR translation is not disabled.
**/
EFI_STATUS
DisableDmar (
VOID
);
/**
Flush VTd engine write buffer.
@param[in] VtdIndex The index used to identify a VTd engine.
**/
VOID
FlushWriteBuffer (
IN UINTN VtdIndex
);
/**
Invalidate VTd context cache.
@param[in] VtdIndex The index used to identify a VTd engine.
**/
EFI_STATUS
InvalidateContextCache (
IN UINTN VtdIndex
);
/**
Invalidate VTd IOTLB.
@param[in] VtdIndex The index used to identify a VTd engine.
**/
EFI_STATUS
InvalidateIOTLB (
IN UINTN VtdIndex
);
/**
Invalid VTd global IOTLB.
@param[in] VtdIndex The index of VTd engine.
@retval EFI_SUCCESS VTd global IOTLB is invalidated.
@retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
**/
EFI_STATUS
InvalidateVtdIOTLBGlobal (
IN UINTN VtdIndex
);
/**
Dump VTd registers.
@param[in] VtdIndex The index of VTd engine.
**/
VOID
DumpVtdRegs (
IN UINTN VtdIndex
);
/**
Dump VTd registers for all VTd engine.
**/
VOID
DumpVtdRegsAll (
VOID
);
/**
Dump VTd capability registers.
@param[in] CapReg The capability register.
**/
VOID
DumpVtdCapRegs (
IN VTD_CAP_REG *CapReg
);
/**
Dump VTd extended capability registers.
@param[in] ECapReg The extended capability register.
**/
VOID
DumpVtdECapRegs (
IN VTD_ECAP_REG *ECapReg
);
/**
Register PCI device to VTd engine.
@param[in] VtdIndex The index of VTd engine.
@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 UINTN VtdIndex,
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId,
IN UINT8 DeviceType,
IN BOOLEAN CheckExist
);
/**
The scan bus callback function to always enable page attribute.
@param[in] Context The context of the callback.
@param[in] Segment The segment of the source.
@param[in] Bus The bus of the source.
@param[in] Device The device of the source.
@param[in] Function The function of the source.
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
**/
EFI_STATUS
EFIAPI
ScanBusCallbackRegisterPciDevice (
IN VOID *Context,
IN UINT16 Segment,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Function
);
/**
Scan PCI bus and invoke callback function for each PCI devices under the bus.
@param[in] Context The context of the callback function.
@param[in] Segment The segment of the source.
@param[in] Bus The bus 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
ScanPciBus (
IN VOID *Context,
IN UINT16 Segment,
IN UINT8 Bus,
IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback
);
/**
Dump the PCI device information managed by this VTd engine.
@param[in] VtdIndex The index of VTd engine.
**/
VOID
DumpPciDeviceInfo (
IN UINTN VtdIndex
);
/**
Find the VTd index by the Segment and SourceId.
@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
FindVtdIndexByPciDevice (
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId,
OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,
OUT VTD_CONTEXT_ENTRY **ContextEntry
);
/**
Get the DMAR ACPI table.
@retval EFI_SUCCESS The DMAR ACPI table is got.
@retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previously.
@retval EFI_NOT_FOUND The DMAR ACPI table is not found.
**/
EFI_STATUS
GetDmarAcpiTable (
VOID
);
/**
Parse DMAR DRHD table.
@return EFI_SUCCESS The DMAR DRHD table is parsed.
**/
EFI_STATUS
ParseDmarAcpiTableDrhd (
VOID
);
/**
Parse DMAR RMRR table.
@return EFI_SUCCESS The DMAR RMRR table is parsed.
**/
EFI_STATUS
ParseDmarAcpiTableRmrr (
VOID
);
/**
Dump DMAR context entry table.
@param[in] RootEntry DMAR root entry.
**/
VOID
DumpDmarContextEntryTable (
IN VTD_ROOT_ENTRY *RootEntry
);
/**
Dump DMAR extended context entry table.
@param[in] ExtRootEntry DMAR extended root entry.
**/
VOID
DumpDmarExtContextEntryTable (
IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
);
/**
Dump DMAR second level paging entry.
@param[in] SecondLevelPagingEntry The second level paging entry.
**/
VOID
DumpSecondLevelPagingEntry (
IN VOID *SecondLevelPagingEntry
);
/**
Set VTd attribute for a system memory.
@param[in] VtdIndex The index used to identify a VTd engine.
@param[in] DomainIdentifier The domain ID of the source.
@param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.
@param[in] BaseAddress The base of device memory address to be used as the DMA memory.
@param[in] Length The length of device memory address to be used as the DMA memory.
@param[in] IoMmuAccess The IOMMU access.
@retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
@retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is 0.
@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 BaseAddress and Length.
@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.
**/
EFI_STATUS
SetPageAttribute (
IN UINTN VtdIndex,
IN UINT16 DomainIdentifier,
IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,
IN UINT64 BaseAddress,
IN UINT64 Length,
IN UINT64 IoMmuAccess
);
/**
Set VTd attribute for a system memory.
@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] BaseAddress The base of device memory address to be used as the DMA memory.
@param[in] Length The length of device memory address to be used as the DMA memory.
@param[in] IoMmuAccess The IOMMU access.
@retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
@retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is 0.
@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 BaseAddress and Length.
@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.
**/
EFI_STATUS
SetAccessAttribute (
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId,
IN UINT64 BaseAddress,
IN UINT64 Length,
IN UINT64 IoMmuAccess
);
/**
Return the index of PCI data.
@param[in] VtdIndex The index used to identify a VTd engine.
@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 UINTN VtdIndex,
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId
);
/**
Dump VTd registers if there is error.
**/
VOID
DumpVtdIfError (
VOID
);
/**
Initialize platform VTd policy.
**/
VOID
InitializePlatformVTdPolicy (
VOID
);
/**
Always enable the VTd page attribute for the device.
@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.
@retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
**/
EFI_STATUS
AlwaysEnablePageAttribute (
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId
);
/**
Convert the DeviceHandle to SourceId and Segment.
@param[in] DeviceHandle The device who initiates the DMA access request.
@param[out] Segment The Segment used to identify a VTd engine.
@param[out] SourceId The SourceId used to identify a VTd engine and table entry.
@retval EFI_SUCCESS The Segment and SourceId are returned.
@retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
@retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
**/
EFI_STATUS
DeviceHandleToSourceId (
IN EFI_HANDLE DeviceHandle,
OUT UINT16 *Segment,
OUT VTD_SOURCE_ID *SourceId
);
/**
Get device information from mapping.
@param[in] Mapping The mapping.
@param[out] DeviceAddress The device address of the mapping.
@param[out] NumberOfPages The number of pages of the mapping.
@retval EFI_SUCCESS The device information is returned.
@retval EFI_INVALID_PARAMETER The mapping is invalid.
**/
EFI_STATUS
GetDeviceInfoFromMapping (
IN VOID *Mapping,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT UINTN *NumberOfPages
);
/**
Initialize DMA protection.
**/
VOID
InitializeDmaProtection (
VOID
);
/**
Allocate zero pages.
@param[in] Pages the number of pages.
@return the page address.
@retval NULL No resource to allocate pages.
**/
VOID *
EFIAPI
AllocateZeroPages (
IN UINTN Pages
);
/**
Flush VTD page table and context table memory.
This action is to make sure the IOMMU engine can get final data in memory.
@param[in] VtdIndex The index used to identify a VTd engine.
@param[in] Base The base address of memory to be flushed.
@param[in] Size The size of memory in bytes to be flushed.
**/
VOID
FlushPageTableMemory (
IN UINTN VtdIndex,
IN UINTN Base,
IN UINTN Size
);
/**
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
);
/**
Append VTd Access Request to global.
@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] BaseAddress The base of device memory address to be used as the DMA memory.
@param[in] Length The length of device memory address to be used as the DMA memory.
@param[in] IoMmuAccess The IOMMU access.
@retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
@retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is 0.
@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 BaseAddress and Length.
@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.
**/
EFI_STATUS
RequestAccessAttribute (
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId,
IN UINT64 BaseAddress,
IN UINT64 Length,
IN UINT64 IoMmuAccess
);
#endif

View File

@ -1,890 +0,0 @@
/** @file
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DmaProtection.h"
#pragma pack(1)
typedef struct {
EFI_ACPI_DESCRIPTION_HEADER Header;
UINT32 Entry;
} RSDT_TABLE;
typedef struct {
EFI_ACPI_DESCRIPTION_HEADER Header;
UINT64 Entry;
} XSDT_TABLE;
#pragma pack()
EFI_ACPI_DMAR_HEADER *mAcpiDmarTable = NULL;
/**
Dump DMAR DeviceScopeEntry.
@param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
**/
VOID
DumpDmarDeviceScopeEntry (
IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
)
{
UINTN PciPathNumber;
UINTN PciPathIndex;
EFI_ACPI_DMAR_PCI_PATH *PciPath;
if (DmarDeviceScopeEntry == NULL) {
return;
}
DEBUG ((DEBUG_INFO,
" *************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
" * DMA-Remapping Device Scope Entry Structure *\n"
));
DEBUG ((DEBUG_INFO,
" *************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
" DMAR Device Scope Entry address ...................... 0x%016lx\n" :
" DMAR Device Scope Entry address ...................... 0x%08x\n",
DmarDeviceScopeEntry
));
DEBUG ((DEBUG_INFO,
" Device Scope Entry Type ............................ 0x%02x\n",
DmarDeviceScopeEntry->Type
));
switch (DmarDeviceScopeEntry->Type) {
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
DEBUG ((DEBUG_INFO,
" PCI Endpoint Device\n"
));
break;
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
DEBUG ((DEBUG_INFO,
" PCI Sub-hierachy\n"
));
break;
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
DEBUG ((DEBUG_INFO,
" IOAPIC\n"
));
break;
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
DEBUG ((DEBUG_INFO,
" MSI Capable HPET\n"
));
break;
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
DEBUG ((DEBUG_INFO,
" ACPI Namespace Device\n"
));
break;
default:
break;
}
DEBUG ((DEBUG_INFO,
" Length ............................................. 0x%02x\n",
DmarDeviceScopeEntry->Length
));
DEBUG ((DEBUG_INFO,
" Enumeration ID ..................................... 0x%02x\n",
DmarDeviceScopeEntry->EnumerationId
));
DEBUG ((DEBUG_INFO,
" Starting Bus Number ................................ 0x%02x\n",
DmarDeviceScopeEntry->StartBusNumber
));
PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
DEBUG ((DEBUG_INFO,
" Device ............................................. 0x%02x\n",
PciPath[PciPathIndex].Device
));
DEBUG ((DEBUG_INFO,
" Function ........................................... 0x%02x\n",
PciPath[PciPathIndex].Function
));
}
DEBUG ((DEBUG_INFO,
" *************************************************************************\n\n"
));
return;
}
/**
Dump DMAR ANDD table.
@param[in] Andd DMAR ANDD table
**/
VOID
DumpDmarAndd (
IN EFI_ACPI_DMAR_ANDD_HEADER *Andd
)
{
if (Andd == NULL) {
return;
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
" * ACPI Name-space Device Declaration Structure *\n"
));
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
" ANDD address ........................................... 0x%016lx\n" :
" ANDD address ........................................... 0x%08x\n",
Andd
));
DEBUG ((DEBUG_INFO,
" Type ................................................. 0x%04x\n",
Andd->Header.Type
));
DEBUG ((DEBUG_INFO,
" Length ............................................... 0x%04x\n",
Andd->Header.Length
));
DEBUG ((DEBUG_INFO,
" ACPI Device Number ................................... 0x%02x\n",
Andd->AcpiDeviceNumber
));
DEBUG ((DEBUG_INFO,
" ACPI Object Name ..................................... '%a'\n",
(Andd + 1)
));
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n\n"
));
return;
}
/**
Dump DMAR RHSA table.
@param[in] Rhsa DMAR RHSA table
**/
VOID
DumpDmarRhsa (
IN EFI_ACPI_DMAR_RHSA_HEADER *Rhsa
)
{
if (Rhsa == NULL) {
return;
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
" * Remapping Hardware Status Affinity Structure *\n"
));
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
" RHSA address ........................................... 0x%016lx\n" :
" RHSA address ........................................... 0x%08x\n",
Rhsa
));
DEBUG ((DEBUG_INFO,
" Type ................................................. 0x%04x\n",
Rhsa->Header.Type
));
DEBUG ((DEBUG_INFO,
" Length ............................................... 0x%04x\n",
Rhsa->Header.Length
));
DEBUG ((DEBUG_INFO,
" Register Base Address ................................ 0x%016lx\n",
Rhsa->RegisterBaseAddress
));
DEBUG ((DEBUG_INFO,
" Proximity Domain ..................................... 0x%08x\n",
Rhsa->ProximityDomain
));
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n\n"
));
return;
}
/**
Dump DMAR ATSR table.
@param[in] Atsr DMAR ATSR table
**/
VOID
DumpDmarAtsr (
IN EFI_ACPI_DMAR_ATSR_HEADER *Atsr
)
{
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
INTN AtsrLen;
if (Atsr == NULL) {
return;
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
" * Root Port ATS Capability Reporting Structure *\n"
));
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
" ATSR address ........................................... 0x%016lx\n" :
" ATSR address ........................................... 0x%08x\n",
Atsr
));
DEBUG ((DEBUG_INFO,
" Type ................................................. 0x%04x\n",
Atsr->Header.Type
));
DEBUG ((DEBUG_INFO,
" Length ............................................... 0x%04x\n",
Atsr->Header.Length
));
DEBUG ((DEBUG_INFO,
" Flags ................................................ 0x%02x\n",
Atsr->Flags
));
DEBUG ((DEBUG_INFO,
" ALL_PORTS .......................................... 0x%02x\n",
Atsr->Flags & EFI_ACPI_DMAR_ATSR_FLAGS_ALL_PORTS
));
DEBUG ((DEBUG_INFO,
" Segment Number ....................................... 0x%04x\n",
Atsr->SegmentNumber
));
AtsrLen = Atsr->Header.Length - sizeof(EFI_ACPI_DMAR_ATSR_HEADER);
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Atsr + 1);
while (AtsrLen > 0) {
DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
AtsrLen -= DmarDeviceScopeEntry->Length;
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n\n"
));
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.
@param[in] Drhd DMAR DRHD table
**/
VOID
DumpDmarDrhd (
IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
)
{
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
INTN DrhdLen;
if (Drhd == NULL) {
return;
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
" * DMA-Remapping Hardware Definition Structure *\n"
));
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
" DRHD address ........................................... 0x%016lx\n" :
" DRHD address ........................................... 0x%08x\n",
Drhd
));
DEBUG ((DEBUG_INFO,
" Type ................................................. 0x%04x\n",
Drhd->Header.Type
));
DEBUG ((DEBUG_INFO,
" Length ............................................... 0x%04x\n",
Drhd->Header.Length
));
DEBUG ((DEBUG_INFO,
" Flags ................................................ 0x%02x\n",
Drhd->Flags
));
DEBUG ((DEBUG_INFO,
" INCLUDE_PCI_ALL .................................... 0x%02x\n",
Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
));
DEBUG ((DEBUG_INFO,
" Segment Number ....................................... 0x%04x\n",
Drhd->SegmentNumber
));
DEBUG ((DEBUG_INFO,
" Register Base Address ................................ 0x%016lx\n",
Drhd->RegisterBaseAddress
));
DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
while (DrhdLen > 0) {
DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
DrhdLen -= DmarDeviceScopeEntry->Length;
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n\n"
));
return;
}
/**
Dump DMAR ACPI table.
@param[in] Dmar DMAR ACPI table
**/
VOID
DumpAcpiDMAR (
IN EFI_ACPI_DMAR_HEADER *Dmar
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
INTN DmarLen;
if (Dmar == NULL) {
return;
}
//
// Dump Dmar table
//
DEBUG ((DEBUG_INFO,
"*****************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
"* DMAR Table *\n"
));
DEBUG ((DEBUG_INFO,
"*****************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
"DMAR address ............................................. 0x%016lx\n" :
"DMAR address ............................................. 0x%08x\n",
Dmar
));
DEBUG ((DEBUG_INFO,
" Table Contents:\n"
));
DEBUG ((DEBUG_INFO,
" Host Address Width ................................... 0x%02x\n",
Dmar->HostAddressWidth
));
DEBUG ((DEBUG_INFO,
" Flags ................................................ 0x%02x\n",
Dmar->Flags
));
DEBUG ((DEBUG_INFO,
" INTR_REMAP ......................................... 0x%02x\n",
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
));
DEBUG ((DEBUG_INFO,
" X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
));
DEBUG ((DEBUG_INFO,
" DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG
));
DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
while (DmarLen > 0) {
switch (DmarHeader->Type) {
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;
case EFI_ACPI_DMAR_TYPE_ATSR:
DumpDmarAtsr ((EFI_ACPI_DMAR_ATSR_HEADER *)DmarHeader);
break;
case EFI_ACPI_DMAR_TYPE_RHSA:
DumpDmarRhsa ((EFI_ACPI_DMAR_RHSA_HEADER *)DmarHeader);
break;
case EFI_ACPI_DMAR_TYPE_ANDD:
DumpDmarAndd ((EFI_ACPI_DMAR_ANDD_HEADER *)DmarHeader);
break;
default:
break;
}
DmarLen -= DmarHeader->Length;
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
}
DEBUG ((DEBUG_INFO,
"*****************************************************************************\n\n"
));
return;
}
/**
Dump DMAR ACPI table.
**/
VOID
VtdDumpDmarTable (
VOID
)
{
DumpAcpiDMAR ((EFI_ACPI_DMAR_HEADER *)(UINTN)mAcpiDmarTable);
}
/**
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;
}
/**
Process DMAR DHRD table.
@param[in] VtdIndex The index of VTd engine.
@param[in] DmarDrhd The DRHD table.
@retval EFI_SUCCESS The DRHD table is processed.
**/
EFI_STATUS
ProcessDhrd (
IN UINTN VtdIndex,
IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
)
{
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
UINT8 Bus;
UINT8 Device;
UINT8 Function;
UINT8 SecondaryBusNumber;
EFI_STATUS Status;
VTD_SOURCE_ID SourceId;
mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress = (UINTN)DmarDrhd->RegisterBaseAddress;
DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
mVtdUnitInformation[VtdIndex].Segment = DmarDrhd->SegmentNumber;
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"));
Status = ScanPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, 0, ScanBusCallbackRegisterPciDevice);
if (EFI_ERROR (Status)) {
return Status;
}
} else {
mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE;
DEBUG ((DEBUG_INFO," ProcessDhrd: without INCLUDE ALL\n"));
}
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 Status;
}
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 (VtdIndex, DmarDrhd->SegmentNumber, SourceId, DmarDevScopeEntry->Type, TRUE);
if (EFI_ERROR (Status)) {
//
// There might be duplication for special device other than standard PCI device.
//
switch (DmarDevScopeEntry->Type) {
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
return Status;
}
}
switch (DmarDevScopeEntry->Type) {
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DmarDrhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
Status = ScanPciBus ((VOID *)VtdIndex, DmarDrhd->SegmentNumber, SecondaryBusNumber, ScanBusCallbackRegisterPciDevice);
if (EFI_ERROR (Status)) {
return Status;
}
break;
default:
break;
}
DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
}
return EFI_SUCCESS;
}
/**
Process DMAR RMRR table.
@param[in] DmarRmrr The RMRR table.
@retval EFI_SUCCESS The RMRR table is processed.
**/
EFI_STATUS
ProcessRmrr (
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," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
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 EFI_DEVICE_ERROR;
}
Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
if (EFI_ERROR (Status)) {
return Status;
}
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 = SetAccessAttribute (
DmarRmrr->SegmentNumber,
SourceId,
DmarRmrr->ReservedMemoryRegionBaseAddress,
DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->ReservedMemoryRegionBaseAddress,
EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
);
if (EFI_ERROR (Status)) {
return Status;
}
DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
}
return EFI_SUCCESS;
}
/**
Get VTd engine number.
**/
UINTN
GetVtdEngineNumber (
VOID
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
UINTN VtdIndex;
VtdIndex = 0;
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->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 ;
}
/**
Parse DMAR DRHD table.
@return EFI_SUCCESS The DMAR DRHD table is parsed.
**/
EFI_STATUS
ParseDmarAcpiTableDrhd (
VOID
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
EFI_STATUS Status;
UINTN VtdIndex;
mVtdUnitNumber = GetVtdEngineNumber ();
DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));
ASSERT (mVtdUnitNumber > 0);
if (mVtdUnitNumber == 0) {
return EFI_DEVICE_ERROR;
}
mVtdUnitInformation = AllocateZeroPool (sizeof(*mVtdUnitInformation) * mVtdUnitNumber);
ASSERT (mVtdUnitInformation != NULL);
if (mVtdUnitInformation == NULL) {
return EFI_OUT_OF_RESOURCES;
}
VtdIndex = 0;
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
switch (DmarHeader->Type) {
case EFI_ACPI_DMAR_TYPE_DRHD:
ASSERT (VtdIndex < mVtdUnitNumber);
Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
if (EFI_ERROR (Status)) {
return Status;
}
VtdIndex++;
break;
default:
break;
}
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
}
ASSERT (VtdIndex == mVtdUnitNumber);
for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {
DumpPciDeviceInfo (VtdIndex);
}
return EFI_SUCCESS ;
}
/**
Parse DMAR DRHD table.
@return EFI_SUCCESS The DMAR DRHD table is parsed.
**/
EFI_STATUS
ParseDmarAcpiTableRmrr (
VOID
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
EFI_STATUS Status;
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
switch (DmarHeader->Type) {
case EFI_ACPI_DMAR_TYPE_RMRR:
Status = ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
if (EFI_ERROR (Status)) {
return Status;
}
break;
default:
break;
}
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
}
return EFI_SUCCESS ;
}
/**
Get the DMAR ACPI table.
@retval EFI_SUCCESS The DMAR ACPI table is got.
@retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previously.
@retval EFI_NOT_FOUND The DMAR ACPI table is not found.
**/
EFI_STATUS
GetDmarAcpiTable (
VOID
)
{
if (mAcpiDmarTable != NULL) {
return EFI_ALREADY_STARTED;
}
mAcpiDmarTable = (EFI_ACPI_DMAR_HEADER *) EfiLocateFirstAcpiTable (
EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE
);
if (mAcpiDmarTable == NULL) {
return EFI_NOT_FOUND;
}
DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));
VtdDumpDmarTable();
return EFI_SUCCESS;
}

View File

@ -1,400 +0,0 @@
/** @file
Intel VTd driver.
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DmaProtection.h"
/**
Provides the controller-specific addresses required to access system memory from a
DMA bus master.
@param This The protocol 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().
@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.
**/
EFI_STATUS
EFIAPI
IoMmuMap (
IN EDKII_IOMMU_PROTOCOL *This,
IN EDKII_IOMMU_OPERATION Operation,
IN VOID *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
);
/**
Completes the Map() operation and releases any corresponding resources.
@param This The protocol instance pointer.
@param 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.
**/
EFI_STATUS
EFIAPI
IoMmuUnmap (
IN EDKII_IOMMU_PROTOCOL *This,
IN VOID *Mapping
);
/**
Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
OperationBusMasterCommonBuffer64 mapping.
@param This The protocol instance pointer.
@param Type This parameter is not used and must be ignored.
@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.
@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.
**/
EFI_STATUS
EFIAPI
IoMmuAllocateBuffer (
IN EDKII_IOMMU_PROTOCOL *This,
IN EFI_ALLOCATE_TYPE Type,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT VOID **HostAddress,
IN UINT64 Attributes
);
/**
Frees memory that was allocated with AllocateBuffer().
@param This The protocol instance pointer.
@param Pages The number of pages to free.
@param 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().
**/
EFI_STATUS
EFIAPI
IoMmuFreeBuffer (
IN EDKII_IOMMU_PROTOCOL *This,
IN UINTN Pages,
IN VOID *HostAddress
);
/**
This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,
based upon the DeviceAddress.
@param[in] DeviceHandle The device who initiates the DMA access request.
@param[in] DeviceAddress The base of device memory address to be used as the DMA memory.
@param[in] Length The length of device memory address to be used as the DMA memory.
@param[in] IoMmuAccess The IOMMU access.
**/
VOID
SyncDeviceHandleToMapInfo (
IN EFI_HANDLE DeviceHandle,
IN EFI_PHYSICAL_ADDRESS DeviceAddress,
IN UINT64 Length,
IN UINT64 IoMmuAccess
);
/**
Convert the DeviceHandle to SourceId and Segment.
@param[in] DeviceHandle The device who initiates the DMA access request.
@param[out] Segment The Segment used to identify a VTd engine.
@param[out] SourceId The SourceId used to identify a VTd engine and table entry.
@retval EFI_SUCCESS The Segment and SourceId are returned.
@retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
@retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
**/
EFI_STATUS
DeviceHandleToSourceId (
IN EFI_HANDLE DeviceHandle,
OUT UINT16 *Segment,
OUT VTD_SOURCE_ID *SourceId
)
{
EFI_PCI_IO_PROTOCOL *PciIo;
UINTN Seg;
UINTN Bus;
UINTN Dev;
UINTN Func;
EFI_STATUS Status;
EDKII_PLATFORM_VTD_DEVICE_INFO DeviceInfo;
Status = EFI_NOT_FOUND;
if (mPlatformVTdPolicy != NULL) {
Status = mPlatformVTdPolicy->GetDeviceId (mPlatformVTdPolicy, DeviceHandle, &DeviceInfo);
if (!EFI_ERROR(Status)) {
*Segment = DeviceInfo.Segment;
*SourceId = DeviceInfo.SourceId;
return EFI_SUCCESS;
}
}
Status = gBS->HandleProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);
if (EFI_ERROR(Status)) {
return EFI_UNSUPPORTED;
}
Status = PciIo->GetLocation (PciIo, &Seg, &Bus, &Dev, &Func);
if (EFI_ERROR(Status)) {
return EFI_UNSUPPORTED;
}
*Segment = (UINT16)Seg;
SourceId->Bits.Bus = (UINT8)Bus;
SourceId->Bits.Device = (UINT8)Dev;
SourceId->Bits.Function = (UINT8)Func;
return EFI_SUCCESS;
}
/**
Set IOMMU attribute for a system memory.
If the IOMMU protocol exists, the system memory cannot be used
for DMA by default.
When a device requests a DMA access for a system memory,
the device driver need use SetAttribute() to update the IOMMU
attribute to request DMA access (read and/or write).
The DeviceHandle is used to identify which device submits the request.
The IOMMU implementation need translate the device path to an IOMMU device ID,
and set IOMMU hardware register accordingly.
1) DeviceHandle can be a standard PCI device.
The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.
The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.
The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE.
After the memory is used, the memory need set 0 to keep it being protected.
2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).
The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDKII_IOMMU_ACCESS_WRITE.
@param[in] This The protocol instance pointer.
@param[in] DeviceHandle The device who initiates the DMA access request.
@param[in] DeviceAddress The base of device memory address to be used as the DMA memory.
@param[in] Length The length of device memory address to be used as the DMA memory.
@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 DeviceHandle is an invalid handle.
@retval EFI_INVALID_PARAMETER DeviceAddress is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
@retval EFI_INVALID_PARAMETER Length is 0.
@retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
@retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
@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 DeviceAddress and Length.
@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.
**/
EFI_STATUS
VTdSetAttribute (
IN EDKII_IOMMU_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
IN EFI_PHYSICAL_ADDRESS DeviceAddress,
IN UINT64 Length,
IN UINT64 IoMmuAccess
)
{
EFI_STATUS Status;
UINT16 Segment;
VTD_SOURCE_ID SourceId;
CHAR8 PerfToken[sizeof("VTD(S0000.B00.D00.F00)")];
UINT32 Identifier;
DumpVtdIfError ();
Status = DeviceHandleToSourceId (DeviceHandle, &Segment, &SourceId);
if (EFI_ERROR(Status)) {
return Status;
}
DEBUG ((DEBUG_VERBOSE, "IoMmuSetAttribute: "));
DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length, IoMmuAccess));
if (mAcpiDmarTable == NULL) {
//
// Record the entry to driver global variable.
// As such once VTd is activated, the setting can be adopted.
//
if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) != 0) {
//
// Force no IOMMU access attribute request recording before DMAR table is installed.
//
ASSERT_EFI_ERROR (EFI_NOT_READY);
return EFI_NOT_READY;
}
Status = RequestAccessAttribute (Segment, SourceId, DeviceAddress, Length, IoMmuAccess);
} else {
PERF_CODE (
AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);
Identifier = (Segment << 16) | SourceId.Uint16;
PERF_START_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);
);
Status = SetAccessAttribute (Segment, SourceId, DeviceAddress, Length, IoMmuAccess);
PERF_CODE (
Identifier = (Segment << 16) | SourceId.Uint16;
PERF_END_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);
);
}
if (!EFI_ERROR(Status)) {
SyncDeviceHandleToMapInfo (
DeviceHandle,
DeviceAddress,
Length,
IoMmuAccess
);
}
return Status;
}
/**
Set IOMMU attribute for a system memory.
If the IOMMU protocol exists, the system memory cannot be used
for DMA by default.
When a device requests a DMA access for a system memory,
the device driver need use SetAttribute() to update the IOMMU
attribute to request DMA access (read and/or write).
The DeviceHandle is used to identify which device submits the request.
The IOMMU implementation need translate the device path to an IOMMU device ID,
and set IOMMU hardware register accordingly.
1) DeviceHandle can be a standard PCI device.
The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.
The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.
The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE.
After the memory is used, the memory need set 0 to keep it being protected.
2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).
The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDKII_IOMMU_ACCESS_WRITE.
@param[in] This The protocol 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 DeviceHandle is an invalid handle.
@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 DeviceHandle is unknown by the IOMMU.
@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.
**/
EFI_STATUS
EFIAPI
IoMmuSetAttribute (
IN EDKII_IOMMU_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
IN VOID *Mapping,
IN UINT64 IoMmuAccess
)
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS DeviceAddress;
UINTN NumberOfPages;
EFI_TPL OriginalTpl;
OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);
Status = GetDeviceInfoFromMapping (Mapping, &DeviceAddress, &NumberOfPages);
if (!EFI_ERROR(Status)) {
Status = VTdSetAttribute (
This,
DeviceHandle,
DeviceAddress,
EFI_PAGES_TO_SIZE(NumberOfPages),
IoMmuAccess
);
}
gBS->RestoreTPL (OriginalTpl);
return Status;
}
EDKII_IOMMU_PROTOCOL mIntelVTd = {
EDKII_IOMMU_PROTOCOL_REVISION,
IoMmuSetAttribute,
IoMmuMap,
IoMmuUnmap,
IoMmuAllocateBuffer,
IoMmuFreeBuffer,
};
/**
Initialize the VTd driver.
@param[in] ImageHandle ImageHandle of the loaded driver
@param[in] SystemTable Pointer to the System Table
@retval EFI_SUCCESS The Protocol is installed.
@retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
@retval EFI_DEVICE_ERROR A device error occurred attempting to initialize the driver.
**/
EFI_STATUS
EFIAPI
IntelVTdInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE Handle;
if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
return EFI_UNSUPPORTED;
}
InitializeDmaProtection ();
Handle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEdkiiIoMmuProtocolGuid, &mIntelVTd,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -1,83 +0,0 @@
## @file
# Intel VTd DXE Driver.
#
# This driver initializes VTd engine based upon DMAR ACPI tables
# and provide DMA protection to PCI or ACPI device.
#
# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = IntelVTdDxe
MODULE_UNI_FILE = IntelVTdDxe.uni
FILE_GUID = 987555D6-595D-4CFA-B895-59B89368BD4D
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = IntelVTdInitialize
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 EBC
#
#
[Sources]
IntelVTdDxe.c
BmDma.c
DmaProtection.c
DmaProtection.h
DmarAcpiTable.c
PciInfo.c
TranslationTable.c
TranslationTableEx.c
VtdReg.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelSiliconPkg/IntelSiliconPkg.dec
[LibraryClasses]
DebugLib
UefiDriverEntryPoint
UefiBootServicesTableLib
BaseLib
IoLib
PciSegmentLib
BaseMemoryLib
MemoryAllocationLib
UefiLib
CacheMaintenanceLib
PerformanceLib
PrintLib
ReportStatusCodeLib
[Guids]
gEfiEventExitBootServicesGuid ## CONSUMES ## Event
## CONSUMES ## SystemTable
## CONSUMES ## Event
gEfiAcpi20TableGuid
## CONSUMES ## SystemTable
## CONSUMES ## Event
gEfiAcpi10TableGuid
[Protocols]
gEdkiiIoMmuProtocolGuid ## PRODUCES
gEfiPciIoProtocolGuid ## CONSUMES
gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES
gEdkiiPlatformVTdPolicyProtocolGuid ## SOMETIMES_CONSUMES
[Pcd]
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES
gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError ## CONSUMES
[Depex]
gEfiPciRootBridgeIoProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
IntelVTdDxeExtra.uni

View File

@ -1,14 +0,0 @@
// /** @file
// IntelVTdDxe Module Localized Abstract and Description Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Intel VTd DXE Driver."
#string STR_MODULE_DESCRIPTION #language en-US "This driver initializes VTd engine based upon DMAR ACPI tables and provide DMA protection to PCI or ACPI device."

View File

@ -1,14 +0,0 @@
// /** @file
// IntelVTdDxe Localized Strings and Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_PROPERTIES_MODULE_NAME
#language en-US
"Intel VTd DXE Driver"

View File

@ -1,373 +0,0 @@
/** @file
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DmaProtection.h"
/**
Return the index of PCI data.
@param[in] VtdIndex The index used to identify a VTd engine.
@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 UINTN VtdIndex,
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId
)
{
UINTN Index;
VTD_SOURCE_ID *PciSourceId;
if (Segment != mVtdUnitInformation[VtdIndex].Segment) {
return (UINTN)-1;
}
for (Index = 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; Index++) {
PciSourceId = &mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[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] VtdIndex The index of VTd engine.
@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 UINTN VtdIndex,
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId,
IN UINT8 DeviceType,
IN BOOLEAN CheckExist
)
{
PCI_DEVICE_INFORMATION *PciDeviceInfo;
VTD_SOURCE_ID *PciSourceId;
UINTN PciDataIndex;
UINTN Index;
PCI_DEVICE_DATA *NewPciDeviceData;
EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId;
PciDeviceInfo = &mVtdUnitInformation[VtdIndex].PciDeviceInfo;
if (PciDeviceInfo->IncludeAllFlag) {
//
// Do not register device in other VTD Unit
//
for (Index = 0; Index < VtdIndex; Index++) {
PciDataIndex = GetPciDataIndex (Index, Segment, SourceId);
if (PciDataIndex != (UINTN)-1) {
DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x already registered by Other Vtd(%d)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, Index));
return EFI_SUCCESS;
}
}
}
PciDataIndex = GetPciDataIndex (VtdIndex, Segment, SourceId);
if (PciDataIndex == (UINTN)-1) {
//
// Register new
//
if (PciDeviceInfo->PciDeviceDataNumber >= PciDeviceInfo->PciDeviceDataMaxNumber) {
//
// Reallocate
//
NewPciDeviceData = AllocateZeroPool (sizeof(*NewPciDeviceData) * (PciDeviceInfo->PciDeviceDataMaxNumber + MAX_VTD_PCI_DATA_NUMBER));
if (NewPciDeviceData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
PciDeviceInfo->PciDeviceDataMaxNumber += MAX_VTD_PCI_DATA_NUMBER;
if (PciDeviceInfo->PciDeviceData != NULL) {
CopyMem (NewPciDeviceData, PciDeviceInfo->PciDeviceData, sizeof(*NewPciDeviceData) * PciDeviceInfo->PciDeviceDataNumber);
FreePool (PciDeviceInfo->PciDeviceData);
}
PciDeviceInfo->PciDeviceData = NewPciDeviceData;
}
ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceDataMaxNumber);
PciSourceId = &PciDeviceInfo->PciDeviceData[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));
PciDeviceId = &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDeviceDataNumber].PciDeviceId;
if ((DeviceType == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) ||
(DeviceType == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {
PciDeviceId->VendorId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, PCI_VENDOR_ID_OFFSET));
PciDeviceId->DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, PCI_DEVICE_ID_OFFSET));
PciDeviceId->RevisionId = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, PCI_REVISION_ID_OFFSET));
DEBUG ((DEBUG_INFO, " (%04x:%04x:%02x", PciDeviceId->VendorId, PciDeviceId->DeviceId, PciDeviceId->RevisionId));
if (DeviceType == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) {
PciDeviceId->SubsystemVendorId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, PCI_SUBSYSTEM_VENDOR_ID_OFFSET));
PciDeviceId->SubsystemDeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, PCI_SUBSYSTEM_ID_OFFSET));
DEBUG ((DEBUG_INFO, ":%04x:%04x", PciDeviceId->SubsystemVendorId, PciDeviceId->SubsystemDeviceId));
}
DEBUG ((DEBUG_INFO, ")"));
}
PciDeviceInfo->PciDeviceData[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;
}
/**
The scan bus callback function to register PCI device.
@param[in] Context The context of the callback.
@param[in] Segment The segment of the source.
@param[in] Bus The bus of the source.
@param[in] Device The device of the source.
@param[in] Function The function of the source.
@retval EFI_SUCCESS The PCI device is registered.
**/
EFI_STATUS
EFIAPI
ScanBusCallbackRegisterPciDevice (
IN VOID *Context,
IN UINT16 Segment,
IN UINT8 Bus,
IN UINT8 Device,
IN UINT8 Function
)
{
VTD_SOURCE_ID SourceId;
UINTN VtdIndex;
UINT8 BaseClass;
UINT8 SubClass;
UINT8 DeviceType;
EFI_STATUS Status;
VtdIndex = (UINTN)Context;
SourceId.Bits.Bus = Bus;
SourceId.Bits.Device = Device;
SourceId.Bits.Function = Function;
DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;
BaseClass = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_CLASSCODE_OFFSET + 2));
if (BaseClass == PCI_CLASS_BRIDGE) {
SubClass = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_CLASSCODE_OFFSET + 1));
if (SubClass == PCI_CLASS_BRIDGE_P2P) {
DeviceType = EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;
}
}
Status = RegisterPciDevice (VtdIndex, Segment, SourceId, DeviceType, FALSE);
return Status;
}
/**
Scan PCI bus and invoke callback function for each PCI devices under the bus.
@param[in] Context The context of the callback function.
@param[in] Segment The segment of the source.
@param[in] Bus The bus 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
ScanPciBus (
IN VOID *Context,
IN UINT16 Segment,
IN UINT8 Bus,
IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback
)
{
UINT8 Device;
UINT8 Function;
UINT8 SecondaryBusNumber;
UINT8 HeaderType;
UINT8 BaseClass;
UINT8 SubClass;
UINT16 VendorID;
UINT16 DeviceID;
EFI_STATUS Status;
// Scan the PCI bus for devices
for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
VendorID = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_VENDOR_ID_OFFSET));
DeviceID = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_DEVICE_ID_OFFSET));
if (VendorID == 0xFFFF && DeviceID == 0xFFFF) {
if (Function == 0) {
//
// If function 0 is not implemented, do not scan other functions.
//
break;
}
continue;
}
Status = Callback (Context, Segment, Bus, Device, Function);
if (EFI_ERROR (Status)) {
return Status;
}
BaseClass = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_CLASSCODE_OFFSET + 2));
if (BaseClass == PCI_CLASS_BRIDGE) {
SubClass = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_CLASSCODE_OFFSET + 1));
if (SubClass == PCI_CLASS_BRIDGE_P2P) {
SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
DEBUG ((DEBUG_INFO," ScanPciBus: PCI bridge S%04x B%02x D%02x F%02x (SecondBus:%02x)\n", Segment, Bus, Device, Function, SecondaryBusNumber));
if (SecondaryBusNumber != 0) {
Status = ScanPciBus (Context, Segment, SecondaryBusNumber, Callback);
if (EFI_ERROR (Status)) {
return Status;
}
}
}
}
if (Function == 0) {
HeaderType = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Device, 0, PCI_HEADER_TYPE_OFFSET));
if ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00) {
//
// It is not a multi-function device, do not scan other functions.
//
break;
}
}
}
}
return EFI_SUCCESS;
}
/**
Dump the PCI device information managed by this VTd engine.
@param[in] VtdIndex The index of VTd engine.
**/
VOID
DumpPciDeviceInfo (
IN UINTN VtdIndex
)
{
UINTN Index;
DEBUG ((DEBUG_INFO,"PCI Device Information (Number 0x%x, IncludeAll - %d):\n",
mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber,
mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag
));
for (Index = 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; Index++) {
DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n",
mVtdUnitInformation[VtdIndex].Segment,
mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Bus,
mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Device,
mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Function
));
}
}
/**
Find the VTd index by the Segment and SourceId.
@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
FindVtdIndexByPciDevice (
IN UINT16 Segment,
IN VTD_SOURCE_ID SourceId,
OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,
OUT VTD_CONTEXT_ENTRY **ContextEntry
)
{
UINTN VtdIndex;
VTD_ROOT_ENTRY *RootEntry;
VTD_CONTEXT_ENTRY *ContextEntryTable;
VTD_CONTEXT_ENTRY *ThisContextEntry;
VTD_EXT_ROOT_ENTRY *ExtRootEntry;
VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;
VTD_EXT_CONTEXT_ENTRY *ThisExtContextEntry;
UINTN PciDataIndex;
for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {
if (Segment != mVtdUnitInformation[VtdIndex].Segment) {
continue;
}
PciDataIndex = GetPciDataIndex (VtdIndex, Segment, SourceId);
if (PciDataIndex == (UINTN)-1) {
continue;
}
// DEBUG ((DEBUG_INFO,"FindVtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable != 0) {
ExtRootEntry = &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[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) {
continue;
}
*ExtContextEntry = ThisExtContextEntry;
*ContextEntry = NULL;
} else {
RootEntry = &mVtdUnitInformation[VtdIndex].RootEntryTable[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) {
continue;
}
*ExtContextEntry = NULL;
*ContextEntry = ThisContextEntry;
}
return VtdIndex;
}
return (UINTN)-1;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,152 +0,0 @@
/** @file
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DmaProtection.h"
/**
Create extended context entry.
@param[in] VtdIndex The index of the VTd engine.
@retval EFI_SUCCESS The extended context entry is created.
@retval EFI_OUT_OF_RESOURCE No enough resource to create extended context entry.
**/
EFI_STATUS
CreateExtContextEntry (
IN UINTN VtdIndex
)
{
UINTN Index;
VOID *Buffer;
UINTN RootPages;
UINTN ContextPages;
VTD_EXT_ROOT_ENTRY *ExtRootEntry;
VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;
VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;
VTD_SOURCE_ID *PciSourceId;
VTD_SOURCE_ID SourceId;
UINTN MaxBusNumber;
UINTN EntryTablePages;
MaxBusNumber = 0;
for (Index = 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; Index++) {
PciSourceId = &mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[Index].PciSourceId;
if (PciSourceId->Bits.Bus > MaxBusNumber) {
MaxBusNumber = PciSourceId->Bits.Bus;
}
}
DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));
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 * (MaxBusNumber + 1);
Buffer = AllocateZeroPages (EntryTablePages);
if (Buffer == NULL) {
DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));
return EFI_OUT_OF_RESOURCES;
}
mVtdUnitInformation[VtdIndex].ExtRootEntryTable = (VTD_EXT_ROOT_ENTRY *)Buffer;
Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);
for (Index = 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; Index++) {
PciSourceId = &mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[Index].PciSourceId;
SourceId.Bits.Bus = PciSourceId->Bits.Bus;
SourceId.Bits.Device = PciSourceId->Bits.Device;
SourceId.Bits.Function = PciSourceId->Bits.Function;
ExtRootEntry = &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[SourceId.Index.RootIndex];
if (ExtRootEntry->Bits.LowerPresent == 0) {
ExtRootEntry->Bits.LowerContextTablePointerLo = (UINT32) RShiftU64 ((UINT64)(UINTN)Buffer, 12);
ExtRootEntry->Bits.LowerContextTablePointerHi = (UINT32) RShiftU64 ((UINT64)(UINTN)Buffer, 32);
ExtRootEntry->Bits.LowerPresent = 1;
ExtRootEntry->Bits.UpperContextTablePointerLo = (UINT32) RShiftU64 ((UINT64)(UINTN)Buffer, 12) + 1;
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) ;
ExtContextEntry = &ExtContextEntryTable[SourceId.Index.ContextIndex];
ExtContextEntry->Bits.TranslationType = 0;
ExtContextEntry->Bits.FaultProcessingDisable = 0;
ExtContextEntry->Bits.Present = 0;
DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n", mVtdUnitInformation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
switch (mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW) {
case BIT1:
ExtContextEntry->Bits.AddressWidth = 0x1;
break;
case BIT2:
ExtContextEntry->Bits.AddressWidth = 0x2;
break;
}
}
FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));
return EFI_SUCCESS;
}
/**
Dump DMAR extended context entry table.
@param[in] ExtRootEntry DMAR extended root entry.
**/
VOID
DumpDmarExtContextEntryTable (
IN VTD_EXT_ROOT_ENTRY *ExtRootEntry
)
{
UINTN Index;
UINTN Index2;
VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;
DEBUG ((DEBUG_INFO,"=========================\n"));
DEBUG ((DEBUG_INFO,"DMAR ExtContext Entry Table:\n"));
DEBUG ((DEBUG_INFO,"ExtRootEntry Address - 0x%x\n", ExtRootEntry));
for (Index = 0; Index < VTD_ROOT_ENTRY_NUMBER; Index++) {
if ((ExtRootEntry[Index].Uint128.Uint64Lo != 0) || (ExtRootEntry[Index].Uint128.Uint64Hi != 0)) {
DEBUG ((DEBUG_INFO," ExtRootEntry(0x%02x) B%02x - 0x%016lx %016lx\n",
Index, Index, ExtRootEntry[Index].Uint128.Uint64Hi, ExtRootEntry[Index].Uint128.Uint64Lo));
}
if (ExtRootEntry[Index].Bits.LowerPresent == 0) {
continue;
}
ExtContextEntry = (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(ExtRootEntry[Index].Bits.LowerContextTablePointerLo, ExtRootEntry[Index].Bits.LowerContextTablePointerHi);
for (Index2 = 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER/2; Index2++) {
if ((ExtContextEntry[Index2].Uint256.Uint64_1 != 0) || (ExtContextEntry[Index2].Uint256.Uint64_2 != 0) ||
(ExtContextEntry[Index2].Uint256.Uint64_3 != 0) || (ExtContextEntry[Index2].Uint256.Uint64_4 != 0)) {
DEBUG ((DEBUG_INFO," ExtContextEntryLower(0x%02x) D%02xF%02x - 0x%016lx %016lx %016lx %016lx\n",
Index2, Index2 >> 3, Index2 & 0x7, ExtContextEntry[Index2].Uint256.Uint64_4, ExtContextEntry[Index2].Uint256.Uint64_3, ExtContextEntry[Index2].Uint256.Uint64_2, ExtContextEntry[Index2].Uint256.Uint64_1));
}
if (ExtContextEntry[Index2].Bits.Present == 0) {
continue;
}
DumpSecondLevelPagingEntry ((VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry[Index2].Bits.SecondLevelPageTranslationPointerHi));
}
if (ExtRootEntry[Index].Bits.UpperPresent == 0) {
continue;
}
ExtContextEntry = (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(ExtRootEntry[Index].Bits.UpperContextTablePointerLo, ExtRootEntry[Index].Bits.UpperContextTablePointerHi);
for (Index2 = 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER/2; Index2++) {
if ((ExtContextEntry[Index2].Uint256.Uint64_1 != 0) || (ExtContextEntry[Index2].Uint256.Uint64_2 != 0) ||
(ExtContextEntry[Index2].Uint256.Uint64_3 != 0) || (ExtContextEntry[Index2].Uint256.Uint64_4 != 0)) {
DEBUG ((DEBUG_INFO," ExtContextEntryUpper(0x%02x) D%02xF%02x - 0x%016lx %016lx %016lx %016lx\n",
Index2, (Index2 + 128) >> 3, (Index2 + 128) & 0x7, ExtContextEntry[Index2].Uint256.Uint64_4, ExtContextEntry[Index2].Uint256.Uint64_3, ExtContextEntry[Index2].Uint256.Uint64_2, ExtContextEntry[Index2].Uint256.Uint64_1));
}
if (ExtContextEntry[Index2].Bits.Present == 0) {
continue;
}
}
}
DEBUG ((DEBUG_INFO,"=========================\n"));
}

View File

@ -1,561 +0,0 @@
/** @file
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DmaProtection.h"
UINTN mVtdUnitNumber;
VTD_UNIT_INFORMATION *mVtdUnitInformation;
BOOLEAN mVtdEnabled;
/**
Flush VTD page table and context table memory.
This action is to make sure the IOMMU engine can get final data in memory.
@param[in] VtdIndex The index used to identify a VTd engine.
@param[in] Base The base address of memory to be flushed.
@param[in] Size The size of memory in bytes to be flushed.
**/
VOID
FlushPageTableMemory (
IN UINTN VtdIndex,
IN UINTN Base,
IN UINTN Size
)
{
if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.C == 0) {
WriteBackDataCacheRange ((VOID *)Base, Size);
}
}
/**
Flush VTd engine write buffer.
@param[in] VtdIndex The index used to identify a VTd engine.
**/
VOID
FlushWriteBuffer (
IN UINTN VtdIndex
)
{
UINT32 Reg32;
if (mVtdUnitInformation[VtdIndex].CapReg.Bits.RWBF != 0) {
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
MmioWrite32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);
do {
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_WBF) != 0);
}
}
/**
Invalidate VTd context cache.
@param[in] VtdIndex The index used to identify a VTd engine.
**/
EFI_STATUS
InvalidateContextCache (
IN UINTN VtdIndex
)
{
UINT64 Reg64;
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
if ((Reg64 & B_CCMD_REG_ICC) != 0) {
DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%d)\n",VtdIndex));
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 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG, Reg64);
do {
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
} while ((Reg64 & B_CCMD_REG_ICC) != 0);
return EFI_SUCCESS;
}
/**
Invalidate VTd IOTLB.
@param[in] VtdIndex The index used to identify a VTd engine.
**/
EFI_STATUS
InvalidateIOTLB (
IN UINTN VtdIndex
)
{
UINT64 Reg64;
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].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(%d)\n", VtdIndex));
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 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
do {
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
} while ((Reg64 & B_IOTLB_REG_IVT) != 0);
return EFI_SUCCESS;
}
/**
Invalid VTd global IOTLB.
@param[in] VtdIndex The index of VTd engine.
@retval EFI_SUCCESS VTd global IOTLB is invalidated.
@retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
**/
EFI_STATUS
InvalidateVtdIOTLBGlobal (
IN UINTN VtdIndex
)
{
if (!mVtdEnabled) {
return EFI_SUCCESS;
}
DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));
//
// Write Buffer Flush before invalidation
//
FlushWriteBuffer (VtdIndex);
//
// Invalidate the context cache
//
if (mVtdUnitInformation[VtdIndex].HasDirtyContext) {
InvalidateContextCache (VtdIndex);
}
//
// Invalidate the IOTLB cache
//
if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation[VtdIndex].HasDirtyPages) {
InvalidateIOTLB (VtdIndex);
}
return EFI_SUCCESS;
}
/**
Prepare VTD configuration.
**/
VOID
PrepareVtdConfig (
VOID
)
{
UINTN Index;
UINTN DomainNumber;
for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));
mVtdUnitInformation[Index].CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);
mVtdUnitInformation[Index].ECapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_ECAP_REG);
DumpVtdECapRegs (&mVtdUnitInformation[Index].ECapReg);
if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) == 0) {
DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !!!!\n", Index));
}
if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) == 0) {
DEBUG((DEBUG_ERROR, "!!!! 4-level page-table is not supported on VTD %d !!!!\n", Index));
return ;
}
DomainNumber = (UINTN)1 << (UINT8)((UINTN)mVtdUnitInformation[Index].CapReg.Bits.ND * 2 + 4);
if (mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceDataNumber >= DomainNumber) {
DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceDataNumber, DomainNumber));
return ;
}
}
return ;
}
/**
Disable PMR in all VTd engine.
**/
VOID
DisablePmr (
VOID
)
{
UINT32 Reg32;
VTD_CAP_REG CapReg;
UINTN Index;
DEBUG ((DEBUG_INFO,"DisablePmr\n"));
for (Index = 0; Index < mVtdUnitNumber; Index++) {
CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
continue ;
}
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
if ((Reg32 & BIT0) != 0) {
MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
do {
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
} while((Reg32 & BIT0) != 0);
DEBUG ((DEBUG_INFO,"Pmr(%d) disabled\n", Index));
} else {
DEBUG ((DEBUG_INFO,"Pmr(%d) not enabled\n", Index));
}
}
return ;
}
/**
Enable DMAR translation.
@retval EFI_SUCCESS DMAR translation is enabled.
@retval EFI_DEVICE_ERROR DMAR translation is not enabled.
**/
EFI_STATUS
EnableDmar (
VOID
)
{
UINTN Index;
UINT32 Reg32;
for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));
if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Index].ExtRootEntryTable));
MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].ExtRootEntryTable | BIT11);
} else {
DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[Index].RootEntryTable));
MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);
}
MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
do {
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
//
// Init DMAr Fault Event and Data registers
//
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_FEDATA_REG);
//
// Write Buffer Flush before invalidation
//
FlushWriteBuffer (Index);
//
// Invalidate the context cache
//
InvalidateContextCache (Index);
//
// Invalidate the IOTLB cache
//
InvalidateIOTLB (Index);
//
// Enable VTd
//
MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);
DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
do {
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_TE) == 0);
DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
}
//
// Need disable PMR, since we already setup translation table.
//
DisablePmr ();
mVtdEnabled = TRUE;
return EFI_SUCCESS;
}
/**
Disable DMAR translation.
@retval EFI_SUCCESS DMAR translation is disabled.
@retval EFI_DEVICE_ERROR DMAR translation is not disabled.
**/
EFI_STATUS
DisableDmar (
VOID
)
{
UINTN Index;
UINTN SubIndex;
UINT32 Reg32;
for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n", Index));
//
// Write Buffer Flush before invalidation
//
FlushWriteBuffer (Index);
//
// Disable VTd
//
MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
do {
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));
}
mVtdEnabled = FALSE;
for (Index = 0; Index < mVtdUnitNumber; Index++) {
DEBUG((DEBUG_INFO, "engine [%d] access\n", Index));
for (SubIndex = 0; SubIndex < mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceDataNumber; SubIndex++) {
DEBUG ((DEBUG_INFO, " PCI S%04X B%02x D%02x F%02x - %d\n",
mVtdUnitInformation[Index].Segment,
mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Bus,
mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Device,
mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].PciSourceId.Bits.Function,
mVtdUnitInformation[Index].PciDeviceInfo.PciDeviceData[Index].AccessCount
));
}
}
return EFI_SUCCESS;
}
/**
Dump VTd capability registers.
@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));
}
/**
Dump VTd extended capability registers.
@param[in] ECapReg The extended capability register.
**/
VOID
DumpVtdECapRegs (
IN VTD_ECAP_REG *ECapReg
)
{
DEBUG((DEBUG_INFO, " ECapReg:\n", ECapReg->Uint64));
DEBUG((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C));
DEBUG((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI));
DEBUG((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT));
DEBUG((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR));
DEBUG((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM));
DEBUG((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT));
DEBUG((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC));
DEBUG((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO));
DEBUG((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV));
DEBUG((DEBUG_INFO, " 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));
}
/**
Dump VTd registers.
@param[in] VtdIndex The index of VTd engine.
**/
VOID
DumpVtdRegs (
IN UINTN VtdIndex
)
{
UINTN Index;
UINT64 Reg64;
VTD_FRCD_REG FrcdReg;
VTD_CAP_REG CapReg;
UINT32 Reg32;
VTD_SOURCE_ID SourceId;
DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) Begin ####\n", VtdIndex));
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_VER_REG);
DEBUG((DEBUG_INFO, " VER_REG - 0x%08x\n", Reg32));
CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CAP_REG);
DEBUG((DEBUG_INFO, " CAP_REG - 0x%016lx\n", CapReg.Uint64));
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_ECAP_REG);
DEBUG((DEBUG_INFO, " ECAP_REG - 0x%016lx\n", Reg64));
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_GSTS_REG);
DEBUG((DEBUG_INFO, " GSTS_REG - 0x%08x \n", Reg32));
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR_REG);
DEBUG((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", Reg64));
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD_REG);
DEBUG((DEBUG_INFO, " CCMD_REG - 0x%016lx\n", Reg64));
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FSTS_REG);
DEBUG((DEBUG_INFO, " FSTS_REG - 0x%08x\n", Reg32));
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FECTL_REG);
DEBUG((DEBUG_INFO, " FECTL_REG - 0x%08x\n", Reg32));
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEDATA_REG);
DEBUG((DEBUG_INFO, " FEDATA_REG - 0x%08x\n", Reg32));
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEADDR_REG);
DEBUG((DEBUG_INFO, " FEADDR_REG - 0x%08x\n",Reg32));
Reg32 = MmioRead32 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_FEUADDR_REG);
DEBUG((DEBUG_INFO, " FEUADDR_REG - 0x%08x\n",Reg32));
for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));
FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
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)));
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, " Reason - %x (Refer to VTd Spec, Appendix A)\n", FrcdReg.Bits.FR));
}
}
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IVA_REG);
DEBUG((DEBUG_INFO, " IVA_REG - 0x%016lx\n",Reg64));
Reg64 = MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
DEBUG((DEBUG_INFO, " IOTLB_REG - 0x%016lx\n",Reg64));
DEBUG((DEBUG_INFO, "#### DumpVtdRegs(%d) End ####\n", VtdIndex));
}
/**
Dump VTd registers for all VTd engine.
**/
VOID
DumpVtdRegsAll (
VOID
)
{
UINTN Num;
for (Num = 0; Num < mVtdUnitNumber; Num++) {
DumpVtdRegs (Num);
}
}
/**
Dump VTd registers if there is error.
**/
VOID
DumpVtdIfError (
VOID
)
{
UINTN Num;
UINTN Index;
VTD_FRCD_REG FrcdReg;
VTD_CAP_REG CapReg;
UINT32 Reg32;
BOOLEAN HasError;
for (Num = 0; Num < mVtdUnitNumber; Num++) {
HasError = FALSE;
Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG);
if (Reg32 != 0) {
HasError = TRUE;
}
Reg32 = MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FECTL_REG);
if ((Reg32 & BIT30) != 0) {
HasError = TRUE;
}
CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_CAP_REG);
for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));
FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
if (FrcdReg.Bits.F != 0) {
HasError = TRUE;
}
}
if (HasError) {
REPORT_STATUS_CODE (EFI_ERROR_CODE, PcdGet32 (PcdErrorCodeVTdError));
DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));
DumpVtdRegs (Num);
DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));
//
// Clear
//
for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
if (FrcdReg.Bits.F != 0) {
//
// Software writes the value read from this field (F) to Clear it.
//
MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.Uint64[1]);
}
}
MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG));
}
}
}

View File

@ -1,578 +0,0 @@
/** @file
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <PiPei.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <IndustryStandard/Vtd.h>
#include <Ppi/VtdInfo.h>
#include "IntelVTdPmrPei.h"
/**
Dump DMAR DeviceScopeEntry.
@param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
**/
VOID
DumpDmarDeviceScopeEntry (
IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
)
{
UINTN PciPathNumber;
UINTN PciPathIndex;
EFI_ACPI_DMAR_PCI_PATH *PciPath;
if (DmarDeviceScopeEntry == NULL) {
return;
}
DEBUG ((DEBUG_INFO,
" *************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
" * DMA-Remapping Device Scope Entry Structure *\n"
));
DEBUG ((DEBUG_INFO,
" *************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
" DMAR Device Scope Entry address ...................... 0x%016lx\n" :
" DMAR Device Scope Entry address ...................... 0x%08x\n",
DmarDeviceScopeEntry
));
DEBUG ((DEBUG_INFO,
" Device Scope Entry Type ............................ 0x%02x\n",
DmarDeviceScopeEntry->Type
));
switch (DmarDeviceScopeEntry->Type) {
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
DEBUG ((DEBUG_INFO,
" PCI Endpoint Device\n"
));
break;
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
DEBUG ((DEBUG_INFO,
" PCI Sub-hierachy\n"
));
break;
default:
break;
}
DEBUG ((DEBUG_INFO,
" Length ............................................. 0x%02x\n",
DmarDeviceScopeEntry->Length
));
DEBUG ((DEBUG_INFO,
" Enumeration ID ..................................... 0x%02x\n",
DmarDeviceScopeEntry->EnumerationId
));
DEBUG ((DEBUG_INFO,
" Starting Bus Number ................................ 0x%02x\n",
DmarDeviceScopeEntry->StartBusNumber
));
PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
DEBUG ((DEBUG_INFO,
" Device ............................................. 0x%02x\n",
PciPath[PciPathIndex].Device
));
DEBUG ((DEBUG_INFO,
" Function ........................................... 0x%02x\n",
PciPath[PciPathIndex].Function
));
}
DEBUG ((DEBUG_INFO,
" *************************************************************************\n\n"
));
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.
@param[in] Drhd DMAR DRHD table
**/
VOID
DumpDmarDrhd (
IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
)
{
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
INTN DrhdLen;
if (Drhd == NULL) {
return;
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
" * DMA-Remapping Hardware Definition Structure *\n"
));
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
" DRHD address ........................................... 0x%016lx\n" :
" DRHD address ........................................... 0x%08x\n",
Drhd
));
DEBUG ((DEBUG_INFO,
" Type ................................................. 0x%04x\n",
Drhd->Header.Type
));
DEBUG ((DEBUG_INFO,
" Length ............................................... 0x%04x\n",
Drhd->Header.Length
));
DEBUG ((DEBUG_INFO,
" Flags ................................................ 0x%02x\n",
Drhd->Flags
));
DEBUG ((DEBUG_INFO,
" INCLUDE_PCI_ALL .................................... 0x%02x\n",
Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
));
DEBUG ((DEBUG_INFO,
" Segment Number ....................................... 0x%04x\n",
Drhd->SegmentNumber
));
DEBUG ((DEBUG_INFO,
" Register Base Address ................................ 0x%016lx\n",
Drhd->RegisterBaseAddress
));
DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
while (DrhdLen > 0) {
DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
DrhdLen -= DmarDeviceScopeEntry->Length;
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
}
DEBUG ((DEBUG_INFO,
" ***************************************************************************\n\n"
));
return;
}
/**
Dump DMAR ACPI table.
@param[in] Dmar DMAR ACPI table
**/
VOID
DumpAcpiDMAR (
IN EFI_ACPI_DMAR_HEADER *Dmar
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
INTN DmarLen;
if (Dmar == NULL) {
return;
}
//
// Dump Dmar table
//
DEBUG ((DEBUG_INFO,
"*****************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
"* DMAR Table *\n"
));
DEBUG ((DEBUG_INFO,
"*****************************************************************************\n"
));
DEBUG ((DEBUG_INFO,
(sizeof(UINTN) == sizeof(UINT64)) ?
"DMAR address ............................................. 0x%016lx\n" :
"DMAR address ............................................. 0x%08x\n",
Dmar
));
DEBUG ((DEBUG_INFO,
" Table Contents:\n"
));
DEBUG ((DEBUG_INFO,
" Host Address Width ................................... 0x%02x\n",
Dmar->HostAddressWidth
));
DEBUG ((DEBUG_INFO,
" Flags ................................................ 0x%02x\n",
Dmar->Flags
));
DEBUG ((DEBUG_INFO,
" INTR_REMAP ......................................... 0x%02x\n",
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
));
DEBUG ((DEBUG_INFO,
" X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
));
DEBUG ((DEBUG_INFO,
" DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG
));
DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
while (DmarLen > 0) {
switch (DmarHeader->Type) {
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;
}
DmarLen -= DmarHeader->Length;
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
}
DEBUG ((DEBUG_INFO,
"*****************************************************************************\n\n"
));
return;
}
/**
Get VTd engine number.
@param[in] AcpiDmarTable DMAR ACPI table
@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 ;
}
/**
Process DMAR DHRD 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 (
IN VTD_INFO *VTdInfo,
IN UINTN VtdIndex,
IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
)
{
DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
VTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
}
/**
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
)
{
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(UINT64));
ASSERT(VTdInfo != NULL);
if (VTdInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize the engine mask to all.
//
VTdInfo->AcpiDmarTable = AcpiDmarTable;
VTdInfo->EngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
VTdInfo->VTdEngineCount = 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, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
VtdIndex++;
break;
default:
break;
}
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
}
ASSERT (VtdIndex == VtdUnitNumber);
return EFI_SUCCESS;
}
/**
Return the VTd engine index according to the Segment and DevScopeEntry.
@param AcpiDmarTable DMAR ACPI table
@param Segment The segment of the VTd engine
@param DevScopeEntry The DevScopeEntry of the VTd engine
@return The VTd engine index according to the Segment and DevScopeEntry.
@retval -1 The VTd engine is not found.
**/
UINTN
GetVTdEngineFromDevScopeEntry (
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
IN UINT16 Segment,
IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
)
{
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
UINTN VtdIndex;
EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;
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:
DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
if (DmarDrhd->SegmentNumber != Segment) {
// Mismatch
break;
}
if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
// No DevScopeEntry
// Do not handle PCI_ALL
break;
}
ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
(CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
return VtdIndex;
}
ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
}
break;
default:
break;
}
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
}
return (UINTN)-1;
}
/**
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;
UINTN VTdIndex;
UINT64 RmrrMask;
UINTN LowBottom;
UINTN LowTop;
UINTN HighBottom;
UINT64 HighTop;
EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
AcpiDmarTable = VTdInfo->AcpiDmarTable;
DEBUG ((DEBUG_INFO," 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) {
ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
VTdIndex = GetVTdEngineFromDevScopeEntry (AcpiDmarTable, DmarRmrr->SegmentNumber, DmarDevScopeEntry);
if (VTdIndex != (UINTN)-1) {
RmrrMask = LShiftU64 (1, VTdIndex);
LowBottom = 0;
LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);
SetDmaProtectedRange (
VTdInfo,
RmrrMask,
0,
(UINT32)(LowTop - LowBottom),
HighBottom,
HighTop - HighBottom
);
//
// Remove the engine from the engine mask.
// The assumption is that any other PEI driver does not access
// the device covered by this engine.
//
VTdInfo->EngineMask = VTdInfo->EngineMask & (~RmrrMask);
}
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 = 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);
}
}

View File

@ -1,420 +0,0 @@
/** @file
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <IndustryStandard/Vtd.h>
#include <Ppi/VtdInfo.h>
#include "IntelVTdPmrPei.h"
/**
Get protected low memory alignment.
@param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@return protected low memory alignment.
**/
UINT32
GetPlmrAlignment (
IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress
)
{
UINT32 Data32;
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, 0xFFFFFFFF);
Data32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG);
Data32 = ~Data32 + 1;
return Data32;
}
/**
Get protected high memory alignment.
@param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@return protected high memory alignment.
**/
UINT64
GetPhmrAlignment (
IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress
)
{
UINT64 Data64;
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
Data64 = ~Data64 + 1;
Data64 = Data64 & (LShiftU64 (1, HostAddressWidth) - 1);
return Data64;
}
/**
Get protected low memory alignment.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected low memory alignment.
**/
UINT32
GetLowMemoryAlignment (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
UINT32 Alignment;
UINT32 FinalAlignment;
FinalAlignment = 0;
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Alignment = GetPlmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
if (FinalAlignment < Alignment) {
FinalAlignment = Alignment;
}
}
return FinalAlignment;
}
/**
Get protected high memory alignment.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected high memory alignment.
**/
UINT64
GetHighMemoryAlignment (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
UINT64 Alignment;
UINT64 FinalAlignment;
FinalAlignment = 0;
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Alignment = GetPhmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
if (FinalAlignment < Alignment) {
FinalAlignment = Alignment;
}
}
return FinalAlignment;
}
/**
Enable PMR in the VTd engine.
@param VtdUnitBaseAddress The base address of the VTd engine.
@retval EFI_SUCCESS The PMR is enabled.
@retval EFI_UNSUPPORTED The PMR is not supported.
**/
EFI_STATUS
EnablePmr (
IN UINTN VtdUnitBaseAddress
)
{
UINT32 Reg32;
VTD_CAP_REG CapReg;
DEBUG ((DEBUG_INFO, "EnablePmr - %x\n", VtdUnitBaseAddress));
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
return EFI_UNSUPPORTED;
}
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
if (Reg32 == 0xFFFFFFFF) {
DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));
ASSERT(FALSE);
}
if ((Reg32 & BIT0) == 0) {
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
} while((Reg32 & BIT0) == 0);
}
DEBUG ((DEBUG_INFO, "EnablePmr - Done\n"));
return EFI_SUCCESS;
}
/**
Disable PMR in the VTd engine.
@param VtdUnitBaseAddress The base address of the VTd engine.
@retval EFI_SUCCESS The PMR is disabled.
@retval EFI_UNSUPPORTED The PMR is not supported.
**/
EFI_STATUS
DisablePmr (
IN UINTN VtdUnitBaseAddress
)
{
UINT32 Reg32;
VTD_CAP_REG CapReg;
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
return EFI_UNSUPPORTED;
}
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
if (Reg32 == 0xFFFFFFFF) {
DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));
ASSERT(FALSE);
}
if ((Reg32 & BIT0) != 0) {
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
} while((Reg32 & BIT0) != 0);
}
return EFI_SUCCESS;
}
/**
Set PMR region in the VTd engine.
@param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@param LowMemoryBase The protected low memory region base.
@param LowMemoryLength The protected low memory region length.
@param HighMemoryBase The protected high memory region base.
@param HighMemoryLength The protected high memory region length.
@retval EFI_SUCCESS The PMR is set to protected region.
@retval EFI_UNSUPPORTED The PMR is not supported.
**/
EFI_STATUS
SetPmrRegion (
IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
IN UINT64 HighMemoryBase,
IN UINT64 HighMemoryLength
)
{
VTD_CAP_REG CapReg;
UINT32 PlmrAlignment;
UINT64 PhmrAlignment;
DEBUG ((DEBUG_INFO, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress));
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
DEBUG ((DEBUG_ERROR, "PLMR/PHMR unsupported\n"));
return EFI_UNSUPPORTED;
}
PlmrAlignment = GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));
PhmrAlignment = GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));
if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||
(LowMemoryLength != ALIGN_VALUE(LowMemoryLength, PlmrAlignment)) ||
(HighMemoryBase != ALIGN_VALUE(HighMemoryBase, PhmrAlignment)) ||
(HighMemoryLength != ALIGN_VALUE(HighMemoryLength, PhmrAlignment))) {
DEBUG ((DEBUG_ERROR, "PLMR/PHMR alignment issue\n"));
return EFI_UNSUPPORTED;
}
if (LowMemoryBase == 0 && LowMemoryLength == 0) {
LowMemoryBase = 0xFFFFFFFF;
}
if (HighMemoryBase == 0 && HighMemoryLength == 0) {
HighMemoryBase = 0xFFFFFFFFFFFFFFFF;
}
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, LowMemoryBase);
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG, LowMemoryBase + LowMemoryLength - 1);
DEBUG ((DEBUG_INFO, "PLMR set done\n"));
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, HighMemoryBase);
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);
DEBUG ((DEBUG_INFO, "PHMR set done\n"));
return EFI_SUCCESS;
}
/**
Set DMA protected region.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@param LowMemoryBase The protected low memory region base.
@param LowMemoryLength The protected low memory region length.
@param HighMemoryBase The protected high memory region base.
@param HighMemoryLength The protected high memory region length.
@retval EFI_SUCCESS The DMA protection is set.
@retval EFI_UNSUPPORTED The DMA protection is not set.
**/
EFI_STATUS
SetDmaProtectedRange (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
IN UINT64 HighMemoryBase,
IN UINT64 HighMemoryLength
)
{
UINTN Index;
EFI_STATUS Status;
DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
Status = SetPmrRegion (
VTdInfo->HostAddressWidth,
(UINTN)VTdInfo->VTdEngineAddress[Index],
LowMemoryBase,
LowMemoryLength,
HighMemoryBase,
HighMemoryLength
);
if (EFI_ERROR(Status)) {
return Status;
}
Status = EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (EFI_ERROR(Status)) {
return Status;
}
}
return EFI_SUCCESS;
}
/**
Diable DMA protection.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@retval EFI_SUCCESS DMA protection is disabled.
**/
EFI_STATUS
DisableDmaProtection (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
EFI_STATUS Status;
DEBUG ((DEBUG_INFO, "DisableDmaProtection - 0x%lx\n", EngineMask));
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
DEBUG ((DEBUG_INFO, "Disabling...%d\n", Index));
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Status = DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (EFI_ERROR(Status)) {
return Status;
}
}
return EFI_SUCCESS;
}
/**
Return if the PMR is enabled.
@param VtdUnitBaseAddress The base address of the VTd engine.
@retval TRUE PMR is enabled.
@retval FALSE PMR is disabled or unsupported.
**/
BOOLEAN
IsPmrEnabled (
IN UINTN VtdUnitBaseAddress
)
{
UINT32 Reg32;
VTD_CAP_REG CapReg;
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
return FALSE;
}
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
if ((Reg32 & BIT0) == 0) {
return FALSE;
}
return TRUE;
}
/**
Return the mask of the VTd engine which is enabled.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return the mask of the VTd engine which is enabled.
**/
UINT64
GetDmaProtectionEnabledEngineMask (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
BOOLEAN Result;
UINT64 EnabledEngineMask;
DEBUG ((DEBUG_INFO, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", EngineMask));
EnabledEngineMask = 0;
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Result = IsPmrEnabled ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (Result) {
EnabledEngineMask |= LShiftU64(1, Index);
}
}
DEBUG ((DEBUG_INFO, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask));
return EnabledEngineMask;
}

View File

@ -1,810 +0,0 @@
/** @file
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <PiPei.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/HobLib.h>
#include <IndustryStandard/Vtd.h>
#include <Ppi/IoMmu.h>
#include <Ppi/VtdInfo.h>
#include <Ppi/MemoryDiscovered.h>
#include <Ppi/EndOfPeiPhase.h>
#include "IntelVTdPmrPei.h"
EFI_GUID mVTdInfoGuid = {
0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }
};
EFI_GUID mDmaBufferInfoGuid = {
0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }
};
typedef struct {
UINTN DmaBufferBase;
UINTN DmaBufferSize;
UINTN DmaBufferCurrentTop;
UINTN DmaBufferCurrentBottom;
} DMA_BUFFER_INFO;
#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
typedef struct {
UINT32 Signature;
EDKII_IOMMU_OPERATION Operation;
UINTN NumberOfBytes;
EFI_PHYSICAL_ADDRESS HostAddress;
EFI_PHYSICAL_ADDRESS DeviceAddress;
} MAP_INFO;
/**
PEI Memory Layout:
+------------------+ <=============== PHMR.Limit (+ alignment) (1 << (HostAddressWidth + 1))
| Mem Resource |
| |
+------------------+ <------- EfiMemoryTop
| PEI allocated |
=========== +==================+ <=============== PHMR.Base
^ | Commom Buf |
| | -------------- |
DMA Buffer | * DMA FREE * |
| | -------------- |
V | Read/Write Buf |
=========== +==================+ <=============== PLMR.Limit (+ alignment)
| PEI allocated |
| -------------- | <------- EfiFreeMemoryTop
| * PEI FREE * |
| -------------- | <------- EfiFreeMemoryBottom
| hob |
| -------------- |
| Stack |
+------------------+ <------- EfiMemoryBottom / Stack Bottom
+------------------+
| Mem Alloc Hob |
+------------------+
| |
| Mem Resource |
+------------------+ <=============== PLMR.Base (0)
**/
/**
Set IOMMU attribute for a system memory.
If the IOMMU PPI exists, the system memory cannot be used
for DMA by default.
When a device requests a DMA access for a system memory,
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] 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.
**/
EFI_STATUS
EFIAPI
PeiIoMmuSetAttribute (
IN EDKII_IOMMU_PPI *This,
IN VOID *Mapping,
IN UINT64 IoMmuAccess
)
{
VOID *Hob;
DMA_BUFFER_INFO *DmaBufferInfo;
Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
if (DmaBufferInfo->DmaBufferCurrentTop == 0) {
return EFI_NOT_AVAILABLE_YET;
}
return EFI_SUCCESS;
}
/**
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().
@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
PeiIoMmuMap (
IN EDKII_IOMMU_PPI *This,
IN EDKII_IOMMU_OPERATION Operation,
IN VOID *HostAddress,
IN OUT UINTN *NumberOfBytes,
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
OUT VOID **Mapping
)
{
MAP_INFO *MapInfo;
UINTN Length;
VOID *Hob;
DMA_BUFFER_INFO *DmaBufferInfo;
Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
if (DmaBufferInfo->DmaBufferCurrentTop == 0) {
return EFI_NOT_AVAILABLE_YET;
}
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
*DeviceAddress = (UINTN)HostAddress;
*Mapping = NULL;
return EFI_SUCCESS;
}
Length = *NumberOfBytes + sizeof(MAP_INFO);
if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
*DeviceAddress = DmaBufferInfo->DmaBufferCurrentBottom;
DmaBufferInfo->DmaBufferCurrentBottom += Length;
MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);
MapInfo->Signature = MAP_INFO_SIGNATURE;
MapInfo->Operation = Operation;
MapInfo->NumberOfBytes = *NumberOfBytes;
MapInfo->HostAddress = (UINTN)HostAddress;
MapInfo->DeviceAddress = *DeviceAddress;
*Mapping = MapInfo;
DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation, (UINTN)*DeviceAddress, MapInfo));
//
// If this is a read operation from the Bus Master's point of view,
// then copy the contents of the real buffer into the mapped buffer
// so the Bus Master can read the contents of the real buffer.
//
if (Operation == EdkiiIoMmuOperationBusMasterRead ||
Operation == EdkiiIoMmuOperationBusMasterRead64) {
CopyMem (
(VOID *) (UINTN) MapInfo->DeviceAddress,
(VOID *) (UINTN) MapInfo->HostAddress,
MapInfo->NumberOfBytes
);
}
return EFI_SUCCESS;
}
/**
Completes the Map() operation and releases any corresponding resources.
@param This The PPI instance pointer.
@param 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.
**/
EFI_STATUS
EFIAPI
PeiIoMmuUnmap (
IN EDKII_IOMMU_PPI *This,
IN VOID *Mapping
)
{
MAP_INFO *MapInfo;
UINTN Length;
VOID *Hob;
DMA_BUFFER_INFO *DmaBufferInfo;
Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
if (DmaBufferInfo->DmaBufferCurrentTop == 0) {
return EFI_NOT_AVAILABLE_YET;
}
if (Mapping == NULL) {
return EFI_SUCCESS;
}
MapInfo = Mapping;
ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);
DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo->Operation, (UINTN)MapInfo->DeviceAddress, MapInfo->NumberOfBytes));
//
// If this is a write operation from the Bus Master's point of view,
// then copy the contents of the mapped buffer into the real buffer
// so the processor can read the contents of the real buffer.
//
if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
CopyMem (
(VOID *) (UINTN) MapInfo->HostAddress,
(VOID *) (UINTN) MapInfo->DeviceAddress,
MapInfo->NumberOfBytes
);
}
Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
if (DmaBufferInfo->DmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
DmaBufferInfo->DmaBufferCurrentBottom -= Length;
}
return EFI_SUCCESS;
}
/**
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.
@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
PeiIoMmuAllocateBuffer (
IN EDKII_IOMMU_PPI *This,
IN EFI_MEMORY_TYPE MemoryType,
IN UINTN Pages,
IN OUT VOID **HostAddress,
IN UINT64 Attributes
)
{
UINTN Length;
VOID *Hob;
DMA_BUFFER_INFO *DmaBufferInfo;
Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
if (DmaBufferInfo->DmaBufferCurrentTop == 0) {
return EFI_NOT_AVAILABLE_YET;
}
Length = EFI_PAGES_TO_SIZE(Pages);
if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
*HostAddress = (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Length);
DmaBufferInfo->DmaBufferCurrentTop -= Length;
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
return EFI_SUCCESS;
}
/**
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.
@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
PeiIoMmuFreeBuffer (
IN EDKII_IOMMU_PPI *This,
IN UINTN Pages,
IN VOID *HostAddress
)
{
UINTN Length;
VOID *Hob;
DMA_BUFFER_INFO *DmaBufferInfo;
Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
if (DmaBufferInfo->DmaBufferCurrentTop == 0) {
return EFI_NOT_AVAILABLE_YET;
}
Length = EFI_PAGES_TO_SIZE(Pages);
if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {
DmaBufferInfo->DmaBufferCurrentTop += Length;
}
return EFI_SUCCESS;
}
EDKII_IOMMU_PPI mIoMmuPpi = {
EDKII_IOMMU_PPI_REVISION,
PeiIoMmuSetAttribute,
PeiIoMmuMap,
PeiIoMmuUnmap,
PeiIoMmuAllocateBuffer,
PeiIoMmuFreeBuffer,
};
CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
&gEdkiiIoMmuPpiGuid,
(VOID *) &mIoMmuPpi
};
/**
Initialize DMA protection.
@param VTdInfo The VTd engine context information.
@retval EFI_SUCCESS the DMA protection is initialized.
@retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.
**/
EFI_STATUS
InitDmaProtection (
IN VTD_INFO *VTdInfo
)
{
EFI_STATUS Status;
UINT32 LowMemoryAlignment;
UINT64 HighMemoryAlignment;
UINTN MemoryAlignment;
UINTN LowBottom;
UINTN LowTop;
UINTN HighBottom;
UINT64 HighTop;
DMA_BUFFER_INFO *DmaBufferInfo;
VOID *Hob;
EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;
EDKII_IOMMU_PPI *OldIoMmuPpi;
Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));
LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
if (LowMemoryAlignment < HighMemoryAlignment) {
MemoryAlignment = (UINTN)HighMemoryAlignment;
} else {
MemoryAlignment = LowMemoryAlignment;
}
ASSERT (DmaBufferInfo->DmaBufferSize == ALIGN_VALUE(DmaBufferInfo->DmaBufferSize, MemoryAlignment));
DmaBufferInfo->DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize), MemoryAlignment);
ASSERT (DmaBufferInfo->DmaBufferBase != 0);
if (DmaBufferInfo->DmaBufferBase == 0) {
DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));
return EFI_OUT_OF_RESOURCES;
}
DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));
DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;
//
// (Re)Install PPI.
//
Status = PeiServicesLocatePpi (
&gEdkiiIoMmuPpiGuid,
0,
&OldDescriptor,
(VOID **) &OldIoMmuPpi
);
if (!EFI_ERROR (Status)) {
Status = PeiServicesReInstallPpi (OldDescriptor, &mIoMmuPpiList);
} else {
Status = PeiServicesInstallPpi (&mIoMmuPpiList);
}
ASSERT_EFI_ERROR (Status);
LowBottom = 0;
LowTop = DmaBufferInfo->DmaBufferBase;
HighBottom = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);
Status = SetDmaProtectedRange (
VTdInfo,
VTdInfo->EngineMask,
(UINT32)LowBottom,
(UINT32)(LowTop - LowBottom),
HighBottom,
HighTop - HighBottom
);
if (EFI_ERROR(Status)) {
FreePages ((VOID *)DmaBufferInfo->DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize));
}
return Status;
}
/**
Initializes the Intel VTd Info.
@retval EFI_SUCCESS Usb bot driver is successfully initialized.
@retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
**/
EFI_STATUS
InitVTdInfo (
VOID
)
{
EFI_STATUS Status;
EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
VOID *Hob;
Status = PeiServicesLocatePpi (
&gEdkiiVTdInfoPpiGuid,
0,
NULL,
(VOID **)&AcpiDmarTable
);
ASSERT_EFI_ERROR(Status);
DumpAcpiDMAR (AcpiDmarTable);
//
// Clear old VTdInfo Hob.
//
Hob = GetFirstGuidHob (&mVTdInfoGuid);
if (Hob != NULL) {
ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID));
}
//
// Get DMAR information to local VTdInfo
//
Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);
if (EFI_ERROR(Status)) {
return Status;
}
//
// NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.
//
return EFI_SUCCESS;
}
/**
Initializes the Intel VTd PMR for all memory.
@retval EFI_SUCCESS Usb bot driver is successfully initialized.
@retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
**/
EFI_STATUS
InitVTdPmrForAll (
VOID
)
{
EFI_STATUS Status;
VOID *Hob;
VTD_INFO *VTdInfo;
UINTN LowBottom;
UINTN LowTop;
UINTN HighBottom;
UINT64 HighTop;
Hob = GetFirstGuidHob (&mVTdInfoGuid);
VTdInfo = GET_GUID_HOB_DATA(Hob);
LowBottom = 0;
LowTop = 0;
HighBottom = 0;
HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);
Status = SetDmaProtectedRange (
VTdInfo,
VTdInfo->EngineMask,
(UINT32)LowBottom,
(UINT32)(LowTop - LowBottom),
HighBottom,
HighTop - HighBottom
);
return Status;
}
/**
Initializes the Intel VTd PMR for DMA buffer.
@retval EFI_SUCCESS Usb bot driver is successfully initialized.
@retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
**/
EFI_STATUS
InitVTdPmrForDma (
VOID
)
{
EFI_STATUS Status;
VOID *Hob;
VTD_INFO *VTdInfo;
Hob = GetFirstGuidHob (&mVTdInfoGuid);
VTdInfo = GET_GUID_HOB_DATA(Hob);
//
// If there is RMRR memory, parse it here.
//
ParseDmarAcpiTableRmrr (VTdInfo);
//
// Allocate a range in PEI memory as DMA buffer
// Mark others to be DMA protected.
//
Status = InitDmaProtection (VTdInfo);
return Status;
}
/**
This function handles S3 resume task at the end of PEI
@param[in] PeiServices Pointer to PEI Services Table.
@param[in] NotifyDesc Pointer to the descriptor for the Notification event that
caused this function to execute.
@param[in] Ppi Pointer to the PPI data associated with this function.
@retval EFI_STATUS Always return EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
S3EndOfPeiNotify(
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
)
{
VOID *Hob;
VTD_INFO *VTdInfo;
UINT64 EngineMask;
DEBUG((DEBUG_INFO, "VTdPmr 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;
DisableDmaProtection (VTdInfo, EngineMask);
}
return EFI_SUCCESS;
}
EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEfiEndOfPeiSignalPpiGuid,
S3EndOfPeiNotify
};
/**
This function handles VTd engine setup
@param[in] PeiServices Pointer to PEI Services Table.
@param[in] NotifyDesc Pointer to the descriptor for the Notification event that
caused this function to execute.
@param[in] Ppi Pointer to the PPI data associated with this function.
@retval EFI_STATUS Always return EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
VTdInfoNotify (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
)
{
EFI_STATUS Status;
VOID *MemoryDiscovered;
UINT64 EnabledEngineMask;
VOID *Hob;
VTD_INFO *VTdInfo;
BOOLEAN MemoryInitialized;
DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));
//
// Check if memory is initialized.
//
MemoryInitialized = FALSE;
Status = PeiServicesLocatePpi (
&gEfiPeiMemoryDiscoveredPpiGuid,
0,
NULL,
&MemoryDiscovered
);
if (!EFI_ERROR(Status)) {
MemoryInitialized = TRUE;
}
DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));
if (!MemoryInitialized) {
//
// If the memory is not initialized,
// Protect all system memory
//
InitVTdInfo ();
InitVTdPmrForAll ();
//
// Install PPI.
//
Status = PeiServicesInstallPpi (&mIoMmuPpiList);
ASSERT_EFI_ERROR(Status);
} else {
//
// If the memory is initialized,
// Allocate DMA buffer and protect rest system memory
//
//
// NOTE: We need reinit VTdInfo because previous information might be overriden.
//
InitVTdInfo ();
Hob = GetFirstGuidHob (&mVTdInfoGuid);
VTdInfo = GET_GUID_HOB_DATA(Hob);
//
// NOTE: We need check if PMR is enabled or not.
//
EnabledEngineMask = GetDmaProtectionEnabledEngineMask (VTdInfo, VTdInfo->EngineMask);
if (EnabledEngineMask != 0) {
EnableVTdTranslationProtection (VTdInfo, EnabledEngineMask);
DisableDmaProtection (VTdInfo, EnabledEngineMask);
}
InitVTdPmrForDma ();
if (EnabledEngineMask != 0) {
DisableVTdTranslationProtection (VTdInfo, EnabledEngineMask);
}
}
return EFI_SUCCESS;
}
EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEdkiiVTdInfoPpiGuid,
VTdInfoNotify
};
/**
Initializes the Intel VTd PMR PEIM.
@param FileHandle Handle of the file being invoked.
@param PeiServices Describes the list of possible PEI Services.
@retval EFI_SUCCESS Usb bot driver is successfully initialized.
@retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
**/
EFI_STATUS
EFIAPI
IntelVTdPmrInitialize (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
DMA_BUFFER_INFO *DmaBufferInfo;
DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n"));
if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
return EFI_UNSUPPORTED;
}
DmaBufferInfo = BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_INFO));
ASSERT(DmaBufferInfo != NULL);
if (DmaBufferInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO));
PeiServicesGetBootMode (&BootMode);
if (BootMode == BOOT_ON_S3_RESUME) {
DmaBufferInfo->DmaBufferSize = PcdGet32 (PcdVTdPeiDmaBufferSizeS3);
} else {
DmaBufferInfo->DmaBufferSize = PcdGet32 (PcdVTdPeiDmaBufferSize);
}
Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);
ASSERT_EFI_ERROR (Status);
//
// Register EndOfPei Notify for S3
//
if (BootMode == BOOT_ON_S3_RESUME) {
Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);
ASSERT_EFI_ERROR (Status);
}
return EFI_SUCCESS;
}

View File

@ -1,159 +0,0 @@
/** @file
The definition for DMA access Library.
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __DMA_ACCESS_LIB_H__
#define __DMA_ACCESS_LIB_H__
typedef struct {
EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
UINT64 EngineMask;
UINT8 HostAddressWidth;
UINTN VTdEngineCount;
UINT64 VTdEngineAddress[1];
} VTD_INFO;
/**
Set DMA protected region.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@param LowMemoryBase The protected low memory region base.
@param LowMemoryLength The protected low memory region length.
@param HighMemoryBase The protected high memory region base.
@param HighMemoryLength The protected high memory region length.
@retval EFI_SUCCESS The DMA protection is set.
@retval EFI_UNSUPPORTED The DMA protection is not set.
**/
EFI_STATUS
SetDmaProtectedRange (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
IN UINT64 HighMemoryBase,
IN UINT64 HighMemoryLength
);
/**
Diable DMA protection.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@retval DMA protection is disabled.
**/
EFI_STATUS
DisableDmaProtection (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
Return if the DMA protection is enabled.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@retval TRUE DMA protection is enabled in at least one VTd engine.
@retval FALSE DMA protection is disabled in all VTd engines.
**/
UINT64
GetDmaProtectionEnabledEngineMask (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
Get protected low memory alignment.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected low memory alignment.
**/
UINT32
GetLowMemoryAlignment (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
Get protected high memory alignment.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected high memory alignment.
**/
UINT64
GetHighMemoryAlignment (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
Enable VTd translation table protection.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
**/
VOID
EnableVTdTranslationProtection (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
Disable VTd translation table protection.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
**/
VOID
DisableVTdTranslationProtection (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
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
);
/**
Parse DMAR DRHD table.
@param VTdInfo The VTd engine context information.
**/
VOID
ParseDmarAcpiTableRmrr (
IN VTD_INFO *VTdInfo
);
/**
Dump DMAR ACPI table.
@param[in] Dmar DMAR ACPI table
**/
VOID
DumpAcpiDMAR (
IN EFI_ACPI_DMAR_HEADER *Dmar
);
extern EFI_GUID mVTdInfoGuid;
#endif

View File

@ -1,60 +0,0 @@
## @file
# Component INF file for the Intel VTd PMR PEIM.
#
# This driver initializes VTd engine based upon EDKII_VTD_INFO_PPI
# and provide DMA protection in PEI.
#
# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010017
BASE_NAME = IntelVTdPmrPei
MODULE_UNI_FILE = IntelVTdPmrPei.uni
FILE_GUID = F906769F-4AED-4A0D-8C7C-FF21B9D1051A
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = IntelVTdPmrInitialize
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelSiliconPkg/IntelSiliconPkg.dec
[Sources]
IntelVTdPmrPei.c
IntelVTdPmrPei.h
IntelVTdPmr.c
DmarTable.c
VtdReg.c
[LibraryClasses]
DebugLib
BaseMemoryLib
BaseLib
PeimEntryPoint
PeiServicesLib
HobLib
IoLib
CacheMaintenanceLib
[Ppis]
gEdkiiIoMmuPpiGuid ## PRODUCES
gEdkiiVTdInfoPpiGuid ## CONSUMES
gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
[Pcd]
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSize ## CONSUMES
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3 ## CONSUMES
[Depex]
gEfiPeiMasterBootModePpiGuid AND
gEdkiiVTdInfoPpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
IntelVTdPmrPeiExtra.uni

View File

@ -1,14 +0,0 @@
// /** @file
// IntelVTdPmrPei Module Localized Abstract and Description Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Intel VTd PMR PEI Driver."
#string STR_MODULE_DESCRIPTION #language en-US "This driver initializes VTd engine based upon EDKII_VTD_INFO_PPI and provide DMA protection to device in PEI."

View File

@ -1,14 +0,0 @@
// /** @file
// IntelVTdPmrPei Localized Strings and Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_PROPERTIES_MODULE_NAME
#language en-US
"Intel VTd PMR PEI Driver"

View File

@ -1,287 +0,0 @@
/** @file
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/CacheMaintenanceLib.h>
#include <IndustryStandard/Vtd.h>
#include <Ppi/VtdInfo.h>
#include "IntelVTdPmrPei.h"
/**
Flush VTD page table and context table memory.
This action is to make sure the IOMMU engine can get final data in memory.
@param[in] Base The base address of memory to be flushed.
@param[in] Size The size of memory in bytes to be flushed.
**/
VOID
FlushPageTableMemory (
IN UINTN Base,
IN UINTN Size
)
{
WriteBackDataCacheRange ((VOID *)Base, Size);
}
/**
Flush VTd engine write buffer.
@param VtdUnitBaseAddress The base address of the VTd engine.
**/
VOID
FlushWriteBuffer (
IN UINTN VtdUnitBaseAddress
)
{
UINT32 Reg32;
VTD_CAP_REG CapReg;
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
if (CapReg.Bits.RWBF != 0) {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_WBF) != 0);
}
}
/**
Invalidate VTd context cache.
@param VtdUnitBaseAddress The base address of the VTd engine.
**/
EFI_STATUS
InvalidateContextCache (
IN UINTN VtdUnitBaseAddress
)
{
UINT64 Reg64;
Reg64 = MmioRead64 (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",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 (VtdUnitBaseAddress + R_CCMD_REG, Reg64);
do {
Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);
} while ((Reg64 & B_CCMD_REG_ICC) != 0);
return EFI_SUCCESS;
}
/**
Invalidate VTd IOTLB.
@param VtdUnitBaseAddress The base address of the VTd engine.
**/
EFI_STATUS
InvalidateIOTLB (
IN UINTN VtdUnitBaseAddress
)
{
UINT64 Reg64;
VTD_ECAP_REG ECapReg;
ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
Reg64 = MmioRead64 (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", 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 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
do {
Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
} while ((Reg64 & B_IOTLB_REG_IVT) != 0);
return EFI_SUCCESS;
}
/**
Enable DMAR translation.
@param VtdUnitBaseAddress The base address of the VTd engine.
@param RootEntryTable The address of the VTd RootEntryTable.
@retval EFI_SUCCESS DMAR translation is enabled.
@retval EFI_DEVICE_ERROR DMAR translation is not enabled.
**/
EFI_STATUS
EnableDmar (
IN UINTN VtdUnitBaseAddress,
IN UINTN RootEntryTable
)
{
UINT32 Reg32;
DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)RootEntryTable);
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
//
// Init DMAr Fault Event and Data registers
//
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
//
// Write Buffer Flush before invalidation
//
FlushWriteBuffer (VtdUnitBaseAddress);
//
// Invalidate the context cache
//
InvalidateContextCache (VtdUnitBaseAddress);
//
// Invalidate the IOTLB cache
//
InvalidateIOTLB (VtdUnitBaseAddress);
//
// Enable VTd
//
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);
DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while ((Reg32 & B_GSTS_REG_TE) == 0);
DEBUG ((DEBUG_INFO,"VTD () enabled!<<<<<<\n"));
return EFI_SUCCESS;
}
/**
Disable DMAR translation.
@param VtdUnitBaseAddress The base address of the VTd engine.
@retval EFI_SUCCESS DMAR translation is disabled.
@retval EFI_DEVICE_ERROR DMAR translation is not disabled.
**/
EFI_STATUS
DisableDmar (
IN UINTN VtdUnitBaseAddress
)
{
UINT32 Reg32;
DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x] \n", VtdUnitBaseAddress));
//
// Write Buffer Flush before invalidation
//
FlushWriteBuffer (VtdUnitBaseAddress);
//
// Disable VTd
//
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
do {
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, 0);
DEBUG ((DEBUG_INFO,"VTD () Disabled!<<<<<<\n"));
return EFI_SUCCESS;
}
/**
Enable VTd translation table protection.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
**/
VOID
EnableVTdTranslationProtection (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
VOID *RootEntryTable;
DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtection - 0x%lx\n", EngineMask));
RootEntryTable = AllocatePages (1);
ASSERT (RootEntryTable != NULL);
if (RootEntryTable == NULL) {
DEBUG ((DEBUG_INFO, " EnableVTdTranslationProtection : OutOfResource\n"));
return ;
}
ZeroMem (RootEntryTable, EFI_PAGES_TO_SIZE(1));
FlushPageTableMemory ((UINTN)RootEntryTable, EFI_PAGES_TO_SIZE(1));
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
EnableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index], (UINTN)RootEntryTable);
}
return ;
}
/**
Disable VTd translation table protection.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
**/
VOID
DisableVTdTranslationProtection (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask));
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
DisableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index]);
}
return ;
}

View File

@ -1,361 +0,0 @@
/** @file
Platform VTd Info Sample PEI driver.
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
#include <Ppi/VtdInfo.h>
#include <Library/PeiServicesLib.h>
#include <Library/DebugLib.h>
#include <Library/PciLib.h>
#include <Library/IoLib.h>
#include <Library/MemoryAllocationLib.h>
#define R_SA_MCHBAR (0x48)
#define R_SA_GGC (0x50)
#define N_SKL_SA_GGC_GGMS_OFFSET (0x6)
#define B_SKL_SA_GGC_GGMS_MASK (0xc0)
#define N_SKL_SA_GGC_GMS_OFFSET (0x8)
#define B_SKL_SA_GGC_GMS_MASK (0xff00)
#define V_SKL_SA_GGC_GGMS_8MB 3
#define R_SA_TOLUD (0xbc)
#define R_SA_MCHBAR_VTD1_OFFSET 0x5400 ///< HW UNIT for IGD
#define R_SA_MCHBAR_VTD2_OFFSET 0x5410 ///< HW UNIT for all other - PEG, USB, SATA etc
EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e, {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
typedef struct {
EFI_ACPI_DMAR_HEADER DmarHeader;
//
// VTd engine 1 - integrated graphic
//
EFI_ACPI_DMAR_DRHD_HEADER Drhd1;
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Drhd11;
EFI_ACPI_DMAR_PCI_PATH Drhd111;
//
// VTd engine 2 - all rest
//
EFI_ACPI_DMAR_DRHD_HEADER Drhd2;
//
// RMRR 1 - integrated graphic
//
EFI_ACPI_DMAR_RMRR_HEADER Rmrr1;
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER Rmrr11;
EFI_ACPI_DMAR_PCI_PATH Rmrr111;
} MY_VTD_INFO_PPI;
MY_VTD_INFO_PPI mPlatformVTdSample = {
{ // DmarHeader
{ // Header
EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
sizeof(MY_VTD_INFO_PPI),
EFI_ACPI_DMAR_REVISION,
},
0x26, // HostAddressWidth
},
{ // Drhd1
{ // Header
EFI_ACPI_DMAR_TYPE_DRHD,
sizeof(EFI_ACPI_DMAR_DRHD_HEADER) +
sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
sizeof(EFI_ACPI_DMAR_PCI_PATH)
},
0, // Flags
0, // Reserved
0, // SegmentNumber
0xFED90000 // RegisterBaseAddress -- TO BE PATCHED
},
{ // Drhd11
EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT,
sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
sizeof(EFI_ACPI_DMAR_PCI_PATH),
0, // Reserved2
0, // EnumerationId
0 // StartBusNumber
},
{ // Drhd111
2, // Device
0 // Function
},
{ // Drhd2
{ // Header
EFI_ACPI_DMAR_TYPE_DRHD,
sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
},
EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
0, // Reserved
0, // SegmentNumber
0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
},
{ // Rmrr1
{ // Header
EFI_ACPI_DMAR_TYPE_RMRR,
sizeof(EFI_ACPI_DMAR_RMRR_HEADER) +
sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
sizeof(EFI_ACPI_DMAR_PCI_PATH)
},
{0}, // Reserved
0, // SegmentNumber
0x0, // ReservedMemoryRegionBaseAddress -- TO BE PATCHED
0x0 // ReservedMemoryRegionLimitAddress -- TO BE PATCHED
},
{ // Rmrr11
EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT,
sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
sizeof(EFI_ACPI_DMAR_PCI_PATH),
0, // Reserved2
0, // EnumerationId
0 // StartBusNumber
},
{ // Rmrr111
2, // Device
0 // Function
},
};
EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEdkiiVTdInfoPpiGuid,
&mPlatformVTdSample
};
typedef struct {
EFI_ACPI_DMAR_HEADER DmarHeader;
//
// VTd engine 2 - all rest
//
EFI_ACPI_DMAR_DRHD_HEADER Drhd2;
} MY_VTD_INFO_NO_IGD_PPI;
MY_VTD_INFO_NO_IGD_PPI mPlatformVTdNoIgdSample = {
{ // DmarHeader
{ // Header
EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
sizeof(MY_VTD_INFO_NO_IGD_PPI),
EFI_ACPI_DMAR_REVISION,
},
0x26, // HostAddressWidth
},
{ // Drhd2
{ // Header
EFI_ACPI_DMAR_TYPE_DRHD,
sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
},
EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
0, // Reserved
0, // SegmentNumber
0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
},
};
EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEdkiiVTdInfoPpiGuid,
&mPlatformVTdNoIgdSample
};
/**
Initialize VTd register.
**/
VOID
InitDmar (
VOID
)
{
UINT32 MchBar;
DEBUG ((DEBUG_INFO, "InitDmar\n"));
MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | BIT0);
DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);
DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
}
/**
Patch Graphic UMA address in RMRR and base address.
**/
EFI_PEI_PPI_DESCRIPTOR *
PatchDmar (
VOID
)
{
UINT32 MchBar;
UINT16 IgdMode;
UINT16 GttMode;
UINT32 IgdMemSize;
UINT32 GttMemSize;
MY_VTD_INFO_PPI *PlatformVTdSample;
EFI_PEI_PPI_DESCRIPTOR *PlatformVTdInfoSampleDesc;
MY_VTD_INFO_NO_IGD_PPI *PlatformVTdNoIgdSample;
EFI_PEI_PPI_DESCRIPTOR *PlatformVTdNoIgdInfoSampleDesc;
DEBUG ((DEBUG_INFO, "PatchDmar\n"));
if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPlatformVTdSample);
ASSERT(PlatformVTdSample != NULL);
PlatformVTdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);
ASSERT(PlatformVTdInfoSampleDesc != NULL);
PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;
///
/// Calculate IGD memsize
///
IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
if (IgdMode < 0xF0) {
IgdMemSize = IgdMode * 32 * (1024) * (1024);
} else {
IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
}
///
/// Calculate GTT mem size
///
GttMemSize = 0;
GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
GttMemSize = (1 << GttMode) * (1024) * (1024);
}
PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress = PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
///
/// Update DRHD structures of DmarTable
///
MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {
PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
} else {
MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);
}
DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET))));
if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
} else {
MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);
}
DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
return PlatformVTdInfoSampleDesc;
} else {
PlatformVTdNoIgdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);
ASSERT(PlatformVTdNoIgdSample != NULL);
PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);
ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);
PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;
///
/// Update DRHD structures of DmarTable
///
MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
} else {
MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);
}
DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
return PlatformVTdNoIgdInfoSampleDesc;
}
}
/**
The callback function for SiliconInitializedPpi.
It reinstalls VTD_INFO_PPI.
@param[in] PeiServices General purpose services available to every PEIM.
@param[in] NotifyDescriptor Notify that this module published.
@param[in] Ppi PPI that was installed.
@retval EFI_SUCCESS The function completed successfully.
**/
EFI_STATUS
EFIAPI
SiliconInitializedPpiNotifyCallback (
IN CONST EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
IN VOID *Ppi
)
{
EFI_STATUS Status;
EFI_PEI_PPI_DESCRIPTOR *PpiDesc;
PpiDesc = PatchDmar ();
Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc, PpiDesc);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
&gEdkiiSiliconInitializedPpiGuid,
(EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback
};
/**
Platform VTd Info sample driver.
@param[in] FileHandle Handle of the file being invoked.
@param[in] PeiServices Describes the list of possible PEI Services.
@retval EFI_SUCCESS if it completed successfully.
**/
EFI_STATUS
EFIAPI
PlatformVTdInfoSampleInitialize (
IN EFI_PEI_FILE_HANDLE FileHandle,
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
EFI_STATUS Status;
BOOLEAN SiliconInitialized;
VOID *SiliconInitializedPpi;
EFI_PEI_PPI_DESCRIPTOR *PpiDesc;
SiliconInitialized = FALSE;
//
// Check if silicon is initialized.
//
Status = PeiServicesLocatePpi (
&gEdkiiSiliconInitializedPpiGuid,
0,
NULL,
&SiliconInitializedPpi
);
if (!EFI_ERROR(Status)) {
SiliconInitialized = TRUE;
}
DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", SiliconInitialized));
if (!SiliconInitialized) {
Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);
InitDmar ();
Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);
ASSERT_EFI_ERROR (Status);
} else {
PpiDesc = PatchDmar ();
Status = PeiServicesInstallPpi (PpiDesc);
ASSERT_EFI_ERROR (Status);
}
return Status;
}

View File

@ -1,48 +0,0 @@
## @file
# Platform VTd Info Sample PEI driver.
#
# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PlatformVTdInfoSamplePei
MODULE_UNI_FILE = PlatformVTdInfoSamplePei.uni
FILE_GUID = 839EB770-5C64-4EED-A6D5-EC515B2B2B23
MODULE_TYPE = PEIM
VERSION_STRING = 1.0
ENTRY_POINT = PlatformVTdInfoSampleInitialize
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 EBC
#
#
[Sources]
PlatformVTdInfoSamplePei.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelSiliconPkg/IntelSiliconPkg.dec
[LibraryClasses]
PeimEntryPoint
PeiServicesLib
DebugLib
PciLib
IoLib
[Ppis]
gEdkiiVTdInfoPpiGuid ## PRODUCES
[Depex]
gEfiPeiMasterBootModePpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
PlatformVTdInfoSamplePeiExtra.uni

View File

@ -1,14 +0,0 @@
// /** @file
// PlatformVTdInfoSamplePei Module Localized Abstract and Description Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Platform VTd Info PEI Driver."
#string STR_MODULE_DESCRIPTION #language en-US "This driver provides sample on how to produce Platform VTd Info PPI."

View File

@ -1,14 +0,0 @@
// /** @file
// PlatformVTdInfoSamplePei Localized Strings and Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_PROPERTIES_MODULE_NAME
#language en-US
"Platform VTd Info Sample PEI Driver"

View File

@ -1,407 +0,0 @@
/** @file
Platform VTd Sample driver.
Note: This module should only be used for dev/debug purposes.
It MUST never be used for production builds.
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiDxe.h>
#include <IndustryStandard/Vtd.h>
#include <Protocol/PlatformVtdPolicy.h>
#include <Protocol/PciIo.h>
#include <Protocol/DevicePath.h>
#include <Library/IoLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DevicePathLib.h>
#include <IndustryStandard/DmaRemappingReportingTable.h>
typedef struct {
ACPI_EXTENDED_HID_DEVICE_PATH I2cController;
UINT8 HidStr[8];
UINT8 UidStr[1];
UINT8 CidStr[8];
} PLATFORM_I2C_CONTROLLER_DEVICE_PATH;
typedef struct {
ACPI_EXTENDED_HID_DEVICE_PATH I2cDevice;
UINT8 HidStr[13];
UINT8 UidStr[1];
UINT8 CidStr[13];
} PLATFORM_I2C_DEVICE_DEVICE_PATH;
typedef struct {
PLATFORM_I2C_CONTROLLER_DEVICE_PATH I2cController;
PLATFORM_I2C_DEVICE_DEVICE_PATH I2cDevice;
EFI_DEVICE_PATH_PROTOCOL End;
} PLATFORM_I2C_DEVICE_PATH;
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
PCI_DEVICE_PATH PciDevice;
EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
} PLATFORM_PCI_DEVICE_PATH;
typedef struct {
ACPI_HID_DEVICE_PATH PciRootBridge;
PCI_DEVICE_PATH PciBridge;
PCI_DEVICE_PATH PciDevice;
EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
} PLATFORM_PCI_BRIDGE_DEVICE_PATH;
typedef struct {
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINT16 Segment;
VTD_SOURCE_ID SourceId;
} PLATFORM_ACPI_DEVICE_MAPPING;
#define PLATFORM_PCI_ROOT_BRIDGE \
{ \
{ \
ACPI_DEVICE_PATH, \
ACPI_DP, \
{ \
(UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
(UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
}, \
}, \
EISA_PNP_ID (0x0A03), \
0 \
}
#define PLATFORM_END_ENTIRE \
{ \
END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { END_DEVICE_PATH_LENGTH, 0 } \
}
#define PLATFORM_PCI(Device, Function) \
{ \
{ \
HARDWARE_DEVICE_PATH, \
HW_PCI_DP, \
{ \
(UINT8) (sizeof (PCI_DEVICE_PATH)), \
(UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
} \
}, \
(Function), \
(Device) \
}
#define PLATFORM_I2C(Hid, Uid, Cid, HidStr, UidStr, CidStr) \
{ \
{ \
{ \
ACPI_DEVICE_PATH, \
ACPI_EXTENDED_DP, \
{sizeof(ACPI_EXTENDED_HID_DEVICE_PATH) + sizeof(HidStr) + sizeof(UidStr) + sizeof(CidStr), 0} \
}, \
Hid, \
Uid, \
Cid \
}, \
HidStr, \
UidStr, \
CidStr \
}
PLATFORM_I2C_DEVICE_PATH mPlatformI2CDevicePath = {
PLATFORM_I2C(0, 2, 0, "INT33C3", "", "INT33C3"),
PLATFORM_I2C(0, 1, 0, "I2C01\\TPANEL", "", "I2C01\\TPANEL"),
PLATFORM_END_ENTIRE
};
PLATFORM_ACPI_DEVICE_MAPPING mAcpiDeviceMapping[] = {
{
(EFI_DEVICE_PATH_PROTOCOL *)&mPlatformI2CDevicePath,
0x0, // Segment
{{0x01, 0x15, 0x00}} // Function, Device, Bus
}
};
PLATFORM_PCI_BRIDGE_DEVICE_PATH mPlatformPciBridgeDevicePath = {
PLATFORM_PCI_ROOT_BRIDGE,
PLATFORM_PCI(0x1C, 1),
PLATFORM_PCI(0, 0),
PLATFORM_END_ENTIRE
};
#pragma pack(1)
typedef struct {
EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo;
EDKII_PLATFORM_VTD_DEVICE_SCOPE DeviceScope;
EFI_ACPI_DMAR_PCI_PATH PciBridge;
EFI_ACPI_DMAR_PCI_PATH PciDevice;
} PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT;
typedef struct {
EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO ExceptionDeviceInfo;
EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId;
} PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT;
#pragma pack()
PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT mExceptionDeviceScopeList[] = {
{
{
EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE,
sizeof(PLATFORM_EXCEPTION_DEVICE_SCOPE_STRUCT)
}, // ExceptionDeviceInfo
{
0, // SegmentNumber
{
EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT, // Type
sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
2 * sizeof(EFI_ACPI_DMAR_PCI_PATH), // Length
0, // Reserved2
0, // EnumerationId
0, // StartBusNumber
},
}, // DeviceScope
{ 0x1C, 1 }, // PciBridge
{ 0x0, 0 }, // PciDevice
},
};
PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT mExceptionPciDeviceIdList[] = {
{
{
EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID,
sizeof(PLATFORM_EXCEPTION_PCI_DEVICE_ID_STRUCT)
}, // ExceptionDeviceInfo
{
0x8086, // VendorId
0x9D2F, // DeviceId
0x21, // RevisionId
0x8086, // SubsystemVendorId
0x7270, // SubsystemDeviceId
},
},
};
/**
Compares 2 device path.
@param[in] DevicePath1 A device path with EndDevicePath node.
@param[in] DevicePath2 A device path with EndDevicePath node.
@retval TRUE 2 device path are identical.
@retval FALSE 2 device path are not identical.
**/
BOOLEAN
CompareDevicePath (
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2
)
{
UINTN Size1;
UINTN Size2;
Size1 = GetDevicePathSize (DevicePath1);
Size2 = GetDevicePathSize (DevicePath2);
if (Size1 != Size2) {
return FALSE;
}
if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {
return FALSE;
}
return TRUE;
}
/**
Get the VTD SourceId from the device handler.
This function is required for non PCI device handler.
Pseudo-algo in Intel VTd driver:
Status = PlatformGetVTdDeviceId ();
if (EFI_ERROR(Status)) {
if (DeviceHandle is PCI) {
Get SourceId from Bus/Device/Function
} else {
return EFI_UNSUPPORTED
}
}
Get VTd engine by Segment/Bus/Device/Function.
@param[in] This The protocol instance pointer.
@param[in] DeviceHandle Device Identifier in UEFI.
@param[out] DeviceInfo DeviceInfo for indentify the VTd engine in ACPI Table
and the VTd page entry.
@retval EFI_SUCCESS The VtdIndex and SourceId are returned.
@retval EFI_INVALID_PARAMETER DeviceHandle is not a valid handler.
@retval EFI_INVALID_PARAMETER DeviceInfo is NULL.
@retval EFI_NOT_FOUND The Segment or SourceId information is NOT found.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
PlatformVTdGetDeviceId (
IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
OUT EDKII_PLATFORM_VTD_DEVICE_INFO *DeviceInfo
)
{
EFI_PCI_IO_PROTOCOL *PciIo;
UINTN Seg;
UINTN Bus;
UINTN Dev;
UINTN Func;
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
UINTN Index;
DEBUG ((DEBUG_VERBOSE, "PlatformVTdGetDeviceId\n"));
if (DeviceInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
if (DeviceHandle == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Handle PCI device
//
Status = gBS->HandleProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (VOID **)&PciIo);
if (!EFI_ERROR(Status)) {
Status = PciIo->GetLocation (PciIo, &Seg, &Bus, &Dev, &Func);
if (EFI_ERROR(Status)) {
return EFI_UNSUPPORTED;
}
DeviceInfo->Segment = (UINT16)Seg;
DeviceInfo->SourceId.Bits.Bus = (UINT8)Bus;
DeviceInfo->SourceId.Bits.Device = (UINT8)Dev;
DeviceInfo->SourceId.Bits.Function = (UINT8)Func;
return EFI_SUCCESS;
}
//
// Handle ACPI device
//
Status = gBS->HandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath);
if (!EFI_ERROR(Status)) {
for (Index = 0; Index < ARRAY_SIZE(mAcpiDeviceMapping); Index++) {
if (CompareDevicePath (mAcpiDeviceMapping[Index].DevicePath, DevicePath)) {
DeviceInfo->Segment = mAcpiDeviceMapping[Index].Segment;
DeviceInfo->SourceId = mAcpiDeviceMapping[Index].SourceId;
return EFI_SUCCESS;
}
}
}
return EFI_NOT_FOUND;
}
/**
Get a list of the exception devices.
The VTd driver should always set ALLOW for the device in this list.
@param[in] This The protocol instance pointer.
@param[out] DeviceInfoCount The count of the list of DeviceInfo.
@param[out] DeviceInfo A callee allocated buffer to hold a list of DeviceInfo.
Each DeviceInfo pointer points to EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO.
@retval EFI_SUCCESS The DeviceInfoCount and DeviceInfo are returned.
@retval EFI_INVALID_PARAMETER DeviceInfoCount is NULL, or DeviceInfo is NULL.
@retval EFI_UNSUPPORTED This function is not supported.
**/
EFI_STATUS
EFIAPI
PlatformVTdGetExceptionDeviceList (
IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL *This,
OUT UINTN *DeviceInfoCount,
OUT VOID **DeviceInfo
)
{
DEBUG ((DEBUG_VERBOSE, "PlatformVTdGetExceptionDeviceList\n"));
if (DeviceInfoCount == NULL || DeviceInfo == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Sample codes for device scope based exception list.
// Uncomment to take affect and comment the sample codes for PCI vendor id
// based exception list.
//
/*
*DeviceInfo = AllocateZeroPool (sizeof(mExceptionDeviceScopeList));
if (*DeviceInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (*DeviceInfo, mExceptionDeviceScopeList, sizeof(mExceptionDeviceScopeList));
*DeviceInfoCount = ARRAY_SIZE(mExceptionDeviceScopeList);
*/
//
// Sample codes for PCI vendor id based exception list.
// Uncomment to take affect and comment the sample codes for device scope
// based exception list.
//
/*
*DeviceInfo = AllocateZeroPool (sizeof(mExceptionPciDeviceIdList));
if (*DeviceInfo == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (*DeviceInfo, mExceptionPciDeviceIdList, sizeof(mExceptionPciDeviceIdList));
*DeviceInfoCount = ARRAY_SIZE(mExceptionPciDeviceIdList);
*/
return EFI_UNSUPPORTED;
}
EDKII_PLATFORM_VTD_POLICY_PROTOCOL mPlatformVTdSample = {
EDKII_PLATFORM_VTD_POLICY_PROTOCOL_REVISION,
PlatformVTdGetDeviceId,
PlatformVTdGetExceptionDeviceList,
};
/**
Platform VTd sample driver.
@param[in] ImageHandle ImageHandle of the loaded driver
@param[in] SystemTable Pointer to the System Table
@retval EFI_SUCCESS The Protocol is installed.
@retval EFI_OUT_OF_RESOURCES Not enough resources available to initialize driver.
@retval EFI_DEVICE_ERROR A device error occurred attempting to initialize the driver.
**/
EFI_STATUS
EFIAPI
PlatformVTdSampleInitialize (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HANDLE Handle;
Handle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&Handle,
&gEdkiiPlatformVTdPolicyProtocolGuid, &mPlatformVTdSample,
NULL
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -1,56 +0,0 @@
## @file
# Platform VTd Sample driver.
#
# Note: This module should only be used for dev/debug purposes.
# It MUST never be used for production builds.
#
# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PlatformVTdSampleDxe
MODULE_UNI_FILE = PlatformVTdSampleDxe.uni
FILE_GUID = 5DFAE03E-9C19-4996-85BF-65297BD4137F
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = PlatformVTdSampleInitialize
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 EBC
#
#
[Sources]
PlatformVTdSampleDxe.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelSiliconPkg/IntelSiliconPkg.dec
[LibraryClasses]
DebugLib
UefiDriverEntryPoint
UefiBootServicesTableLib
BaseLib
IoLib
PciSegmentLib
BaseMemoryLib
MemoryAllocationLib
DevicePathLib
[Protocols]
gEdkiiPlatformVTdPolicyProtocolGuid ## PRODUCES
gEfiPciIoProtocolGuid ## CONSUMES
[Depex]
gEfiPciRootBridgeIoProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
PlatformVTdSampleDxeExtra.uni

View File

@ -1,14 +0,0 @@
// /** @file
// PlatformVTdSampleDxe Module Localized Abstract and Description Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_MODULE_ABSTRACT #language en-US "Platform VTd Sample DXE Driver."
#string STR_MODULE_DESCRIPTION #language en-US "This driver provides sample on how to produce Platform VTd policy protocol."

View File

@ -1,14 +0,0 @@
// /** @file
// PlatformVTdSampleDxe Localized Strings and Content
//
// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// **/
#string STR_PROPERTIES_MODULE_NAME
#language en-US
"Platform VTd Sample DXE Driver"

View File

@ -1,15 +0,0 @@
/** @file
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __MICROCODE_FMP_GUID_H__
#define __MICROCODE_FMP_GUID_H__
#define MICROCODE_FMP_IMAGE_TYPE_ID_GUID { 0x96d4fdcd, 0x1502, 0x424d, { 0x9d, 0x4c, 0x9b, 0x12, 0xd2, 0xdc, 0xae, 0x5c } }
extern EFI_GUID gMicrocodeFmpImageTypeIdGuid;
#endif

View File

@ -1,69 +0,0 @@
/** @file
FirmwareInterfaceTable (FIT) related definitions.
@todo update document/spec reference
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __FIRMWARE_INTERFACE_TABLE_H__
#define __FIRMWARE_INTERFACE_TABLE_H__
//
// FIT Entry type definitions
//
#define FIT_TYPE_00_HEADER 0x00
#define FIT_TYPE_01_MICROCODE 0x01
#define FIT_TYPE_02_STARTUP_ACM 0x02
#define FIT_TYPE_07_BIOS_STARTUP_MODULE 0x07
#define FIT_TYPE_08_TPM_POLICY 0x08
#define FIT_TYPE_09_BIOS_POLICY 0x09
#define FIT_TYPE_0A_TXT_POLICY 0x0A
#define FIT_TYPE_0B_KEY_MANIFEST 0x0B
#define FIT_TYPE_0C_BOOT_POLICY_MANIFEST 0x0C
#define FIT_TYPE_10_CSE_SECURE_BOOT 0x10
#define FIT_TYPE_2D_TXTSX_POLICY 0x2D
#define FIT_TYPE_2F_JMP_DEBUG_POLICY 0x2F
#define FIT_TYPE_7F_SKIP 0x7F
#define FIT_POINTER_ADDRESS 0xFFFFFFC0 ///< Fixed address at 4G - 40h
#define FIT_TYPE_VERSION 0x0100
#define FIT_TYPE_00_SIGNATURE SIGNATURE_64 ('_', 'F', 'I', 'T', '_', ' ', ' ', ' ')
#pragma pack(1)
typedef struct {
/**
Address is the base address of the firmware component
must be aligned on 16 byte boundary
**/
UINT64 Address;
UINT8 Size[3]; ///< Size is the span of the component in multiple of 16 bytes
UINT8 Reserved; ///< Reserved must be set to 0
/**
Component's version number in binary coded decimal (BCD) format.
For the FIT header entry, the value in this field will indicate the revision
number of the FIT data structure. The upper byte of the revision field
indicates the major revision and the lower byte indicates the minor revision.
**/
UINT16 Version;
UINT8 Type : 7; ///< FIT types 0x00 to 0x7F
///
/// Checksum Valid indicates whether component has valid checksum.
///
UINT8 C_V : 1;
/**
Component's checksum. The modulo sum of all the bytes in the component and
the value in this field (Chksum) must add up to zero. This field is only
valid if the C_V flag is non-zero.
**/
UINT8 Chksum;
} FIRMWARE_INTERFACE_TABLE_ENTRY;
#pragma pack()
#endif

View File

@ -1,54 +0,0 @@
/** @file
Intel Firmware Version Info (FVI) related definitions.
@todo update document/spec reference
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Specification Reference:
System Management BIOS (SMBIOS) Reference Specification v3.0.0 dated 2015-Feb-12
http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
**/
#ifndef __FIRMWARE_VERSION_INFO_H__
#define __FIRMWARE_VERSION_INFO_H__
#include <IndustryStandard/SmBios.h>
#define INTEL_FIRMWARE_VERSION_INFO_GROUP_NAME "Firmware Version Info"
#pragma pack(1)
///
/// Firmware Version Structure
///
typedef struct {
UINT8 MajorVersion;
UINT8 MinorVersion;
UINT8 Revision;
UINT16 BuildNumber;
} INTEL_FIRMWARE_VERSION;
///
/// Firmware Version Info (FVI) Structure
///
typedef struct {
SMBIOS_TABLE_STRING ComponentName; ///< String Index of Component Name
SMBIOS_TABLE_STRING VersionString; ///< String Index of Version String
INTEL_FIRMWARE_VERSION Version; ///< Firmware version
} INTEL_FIRMWARE_VERSION_INFO;
///
/// SMBIOS OEM Type Intel Firmware Version Info (FVI) Structure
///
typedef struct {
SMBIOS_STRUCTURE Header; ///< SMBIOS structure header
UINT8 Count; ///< Number of FVI entries in this structure
INTEL_FIRMWARE_VERSION_INFO Fvi[1]; ///< FVI structure(s)
} SMBIOS_TABLE_TYPE_OEM_INTEL_FVI;
#pragma pack()
#endif

View File

@ -1,149 +0,0 @@
/** @file
IGD OpRegion definition from Intel Integrated Graphics Device OpRegion
Specification.
https://01.org/sites/default/files/documentation/skl_opregion_rev0p5.pdf
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _IGD_OPREGION_H_
#define _IGD_OPREGION_H_
#define IGD_OPREGION_HEADER_SIGN "IntelGraphicsMem"
#define IGD_OPREGION_HEADER_MBOX1 BIT0
#define IGD_OPREGION_HEADER_MBOX2 BIT1
#define IGD_OPREGION_HEADER_MBOX3 BIT2
#define IGD_OPREGION_HEADER_MBOX4 BIT3
#define IGD_OPREGION_HEADER_MBOX5 BIT4
/**
OpRegion structures:
Sub-structures define the different parts of the OpRegion followed by the
main structure representing the entire OpRegion.
@note These structures are packed to 1 byte offsets because the exact
data location is required by the supporting design specification due to
the fact that the data is used by ASL and Graphics driver code compiled
separately.
**/
#pragma pack(1)
///
/// OpRegion Mailbox 0 Header structure. The OpRegion Header is used to
/// identify a block of memory as the graphics driver OpRegion.
/// Offset 0x0, Size 0x100
///
typedef struct {
CHAR8 SIGN[0x10]; ///< Offset 0x00 OpRegion Signature
UINT32 SIZE; ///< Offset 0x10 OpRegion Size
UINT32 OVER; ///< Offset 0x14 OpRegion Structure Version
UINT8 SVER[0x20]; ///< Offset 0x18 System BIOS Build Version
UINT8 VVER[0x10]; ///< Offset 0x38 Video BIOS Build Version
UINT8 GVER[0x10]; ///< Offset 0x48 Graphic Driver Build Version
UINT32 MBOX; ///< Offset 0x58 Supported Mailboxes
UINT32 DMOD; ///< Offset 0x5C Driver Model
UINT32 PCON; ///< Offset 0x60 Platform Configuration
CHAR16 DVER[0x10]; ///< Offset 0x64 GOP Version
UINT8 RM01[0x7C]; ///< Offset 0x84 Reserved Must be zero
} IGD_OPREGION_HEADER;
///
/// OpRegion Mailbox 1 - Public ACPI Methods
/// Offset 0x100, Size 0x100
///
typedef struct {
UINT32 DRDY; ///< Offset 0x100 Driver Readiness
UINT32 CSTS; ///< Offset 0x104 Status
UINT32 CEVT; ///< Offset 0x108 Current Event
UINT8 RM11[0x14]; ///< Offset 0x10C Reserved Must be Zero
UINT32 DIDL[8]; ///< Offset 0x120 Supported Display Devices ID List
UINT32 CPDL[8]; ///< Offset 0x140 Currently Attached Display Devices List
UINT32 CADL[8]; ///< Offset 0x160 Currently Active Display Devices List
UINT32 NADL[8]; ///< Offset 0x180 Next Active Devices List
UINT32 ASLP; ///< Offset 0x1A0 ASL Sleep Time Out
UINT32 TIDX; ///< Offset 0x1A4 Toggle Table Index
UINT32 CHPD; ///< Offset 0x1A8 Current Hotplug Enable Indicator
UINT32 CLID; ///< Offset 0x1AC Current Lid State Indicator
UINT32 CDCK; ///< Offset 0x1B0 Current Docking State Indicator
UINT32 SXSW; ///< Offset 0x1B4 Display Switch Notification on Sx State Resume
UINT32 EVTS; ///< Offset 0x1B8 Events supported by ASL
UINT32 CNOT; ///< Offset 0x1BC Current OS Notification
UINT32 NRDY; ///< Offset 0x1C0 Driver Status
UINT8 DID2[0x1C]; ///< Offset 0x1C4 Extended Supported Devices ID List (DOD)
UINT8 CPD2[0x1C]; ///< Offset 0x1E0 Extended Attached Display Devices List
UINT8 RM12[4]; ///< Offset 0x1FC - 0x1FF Reserved Must be zero
} IGD_OPREGION_MBOX1;
///
/// OpRegion Mailbox 2 - Software SCI Interface
/// Offset 0x200, Size 0x100
///
typedef struct {
UINT32 SCIC; ///< Offset 0x200 Software SCI Command / Status / Data
UINT32 PARM; ///< Offset 0x204 Software SCI Parameters
UINT32 DSLP; ///< Offset 0x208 Driver Sleep Time Out
UINT8 RM21[0xF4]; ///< Offset 0x20C - 0x2FF Reserved Must be zero
} IGD_OPREGION_MBOX2;
///
/// OpRegion Mailbox 3 - BIOS/Driver Notification - ASLE Support
/// Offset 0x300, Size 0x100
///
typedef struct {
UINT32 ARDY; ///< Offset 0x300 Driver Readiness
UINT32 ASLC; ///< Offset 0x304 ASLE Interrupt Command / Status
UINT32 TCHE; ///< Offset 0x308 Technology Enabled Indicator
UINT32 ALSI; ///< Offset 0x30C Current ALS Luminance Reading
UINT32 BCLP; ///< Offset 0x310 Requested Backlight Brightness
UINT32 PFIT; ///< Offset 0x314 Panel Fitting State or Request
UINT32 CBLV; ///< Offset 0x318 Current Brightness Level
UINT16 BCLM[0x14]; ///< Offset 0x31C Backlight Brightness Levels Duty Cycle Mapping Table
UINT32 CPFM; ///< Offset 0x344 Current Panel Fitting Mode
UINT32 EPFM; ///< Offset 0x348 Enabled Panel Fitting Modes
UINT8 PLUT[0x4A]; ///< Offset 0x34C Panel Look Up Table & Identifier
UINT32 PFMB; ///< Offset 0x396 PWM Frequency and Minimum Brightness
UINT32 CCDV; ///< Offset 0x39A Color Correction Default Values
UINT32 PCFT; ///< Offset 0x39E Power Conservation Features
UINT32 SROT; ///< Offset 0x3A2 Supported Rotation Angles
UINT32 IUER; ///< Offset 0x3A6 Intel Ultrabook(TM) Event Register
UINT64 FDSS; ///< Offset 0x3AA DSS Buffer address allocated for IFFS feature
UINT32 FDSP; ///< Offset 0x3B2 Size of DSS buffer
UINT32 STAT; ///< Offset 0x3B6 State Indicator
UINT64 RVDA; ///< Offset 0x3BA Physical address of Raw VBT data. Added from Spec Version 0.90 to support VBT greater than 6KB.
UINT32 RVDS; ///< Offset 0x3C2 Size of Raw VBT data. Added from Spec Version 0.90 to support VBT greater than 6KB.
UINT8 RM32[0x3A]; ///< Offset 0x3C6 - 0x3FF Reserved Must be zero.
} IGD_OPREGION_MBOX3;
///
/// OpRegion Mailbox 4 - VBT Video BIOS Table
/// Offset 0x400, Size 0x1800
///
typedef struct {
UINT8 RVBT[0x1800]; ///< Offset 0x400 - 0x1BFF Raw VBT Data
} IGD_OPREGION_MBOX4;
///
/// OpRegion Mailbox 5 - BIOS/Driver Notification - Data storage BIOS to Driver data sync
/// Offset 0x1C00, Size 0x400
///
typedef struct {
UINT32 PHED; ///< Offset 0x1C00 Panel Header
UINT8 BDDC[0x100]; ///< Offset 0x1C04 Panel EDID (DDC data)
UINT8 RM51[0x2FC]; ///< Offset 0x1D04 - 0x1FFF Reserved Must be zero
} IGD_OPREGION_MBOX5;
///
/// IGD OpRegion Structure
///
typedef struct {
IGD_OPREGION_HEADER Header; ///< OpRegion header (Offset 0x0, Size 0x100)
IGD_OPREGION_MBOX1 MBox1; ///< Mailbox 1: Public ACPI Methods (Offset 0x100, Size 0x100)
IGD_OPREGION_MBOX2 MBox2; ///< Mailbox 2: Software SCI Interface (Offset 0x200, Size 0x100)
IGD_OPREGION_MBOX3 MBox3; ///< Mailbox 3: BIOS to Driver Notification (Offset 0x300, Size 0x100)
IGD_OPREGION_MBOX4 MBox4; ///< Mailbox 4: Video BIOS Table (VBT) (Offset 0x400, Size 0x1800)
IGD_OPREGION_MBOX5 MBox5; ///< Mailbox 5: BIOS to Driver Notification Extension (Offset 0x1C00, Size 0x400)
} IGD_OPREGION_STRUCTURE;
#pragma pack()
#endif

View File

@ -1,355 +0,0 @@
/** @file
The definition for VTD register.
It is defined in "Intel VT for Direct IO Architecture Specification".
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __VTD_REG_H__
#define __VTD_REG_H__
#pragma pack(1)
//
// Translation Structure Formats
//
#define VTD_ROOT_ENTRY_NUMBER 256
#define VTD_CONTEXT_ENTRY_NUMBER 256
typedef union {
struct {
UINT32 Present:1;
UINT32 Reserved_1:11;
UINT32 ContextTablePointerLo:20;
UINT32 ContextTablePointerHi:32;
UINT64 Reserved_64;
} Bits;
struct {
UINT64 Uint64Lo;
UINT64 Uint64Hi;
} Uint128;
} VTD_ROOT_ENTRY;
typedef union {
struct {
UINT32 LowerPresent:1;
UINT32 Reserved_1:11;
UINT32 LowerContextTablePointerLo:20;
UINT32 LowerContextTablePointerHi:32;
UINT32 UpperPresent:1;
UINT32 Reserved_65:11;
UINT32 UpperContextTablePointerLo:20;
UINT32 UpperContextTablePointerHi:32;
} Bits;
struct {
UINT64 Uint64Lo;
UINT64 Uint64Hi;
} Uint128;
} VTD_EXT_ROOT_ENTRY;
typedef union {
struct {
UINT32 Present:1;
UINT32 FaultProcessingDisable:1;
UINT32 TranslationType:2;
UINT32 Reserved_4:8;
UINT32 SecondLevelPageTranslationPointerLo:20;
UINT32 SecondLevelPageTranslationPointerHi:32;
UINT32 AddressWidth:3;
UINT32 Ignored_67:4;
UINT32 Reserved_71:1;
UINT32 DomainIdentifier:16;
UINT32 Reserved_88:8;
UINT32 Reserved_96:32;
} Bits;
struct {
UINT64 Uint64Lo;
UINT64 Uint64Hi;
} Uint128;
} VTD_CONTEXT_ENTRY;
typedef union {
struct {
UINT32 Present:1;
UINT32 FaultProcessingDisable:1;
UINT32 TranslationType:3;
UINT32 ExtendedMemoryType:3;
UINT32 DeferredInvalidateEnable:1;
UINT32 PageRequestEnable:1;
UINT32 NestedTranslationEnable:1;
UINT32 PASIDEnable:1;
UINT32 SecondLevelPageTranslationPointerLo:20;
UINT32 SecondLevelPageTranslationPointerHi:32;
UINT32 AddressWidth:3;
UINT32 PageGlobalEnable:1;
UINT32 NoExecuteEnable:1;
UINT32 WriteProtectEnable:1;
UINT32 CacheDisable:1;
UINT32 ExtendedMemoryTypeEnable:1;
UINT32 DomainIdentifier:16;
UINT32 SupervisorModeExecuteProtection:1;
UINT32 ExtendedAccessedFlagEnable:1;
UINT32 ExecuteRequestsEnable:1;
UINT32 SecondLevelExecuteEnable:1;
UINT32 Reserved_92:4;
UINT32 PageAttributeTable0:3;
UINT32 Reserved_Pat0:1;
UINT32 PageAttributeTable1:3;
UINT32 Reserved_Pat1:1;
UINT32 PageAttributeTable2:3;
UINT32 Reserved_Pat2:1;
UINT32 PageAttributeTable3:3;
UINT32 Reserved_Pat3:1;
UINT32 PageAttributeTable4:3;
UINT32 Reserved_Pat4:1;
UINT32 PageAttributeTable5:3;
UINT32 Reserved_Pat5:1;
UINT32 PageAttributeTable6:3;
UINT32 Reserved_Pat6:1;
UINT32 PageAttributeTable7:3;
UINT32 Reserved_Pat7:1;
UINT32 PASIDTableSize:4;
UINT32 Reserved_132:8;
UINT32 PASIDTablePointerLo:20;
UINT32 PASIDTablePointerHi:32;
UINT32 Reserved_192:12;
UINT32 PASIDStateTablePointerLo:20;
UINT32 PASIDStateTablePointerHi:32;
} Bits;
struct {
UINT64 Uint64_1;
UINT64 Uint64_2;
UINT64 Uint64_3;
UINT64 Uint64_4;
} Uint256;
} VTD_EXT_CONTEXT_ENTRY;
typedef union {
struct {
UINT32 Present:1;
UINT32 Reserved_1:2;
UINT32 PageLevelCacheDisable:1;
UINT32 PageLevelWriteThrough:1;
UINT32 Reserved_5:6;
UINT32 SupervisorRequestsEnable:1;
UINT32 FirstLevelPageTranslationPointerLo:20;
UINT32 FirstLevelPageTranslationPointerHi:32;
} Bits;
UINT64 Uint64;
} VTD_PASID_ENTRY;
typedef union {
struct {
UINT32 Reserved_0:32;
UINT32 ActiveReferenceCount:16;
UINT32 Reserved_48:15;
UINT32 DeferredInvalidate:1;
} Bits;
UINT64 Uint64;
} VTD_PASID_STATE_ENTRY;
typedef union {
struct {
UINT32 Present:1;
UINT32 ReadWrite:1;
UINT32 UserSupervisor:1;
UINT32 PageLevelWriteThrough:1;
UINT32 PageLevelCacheDisable:1;
UINT32 Accessed:1;
UINT32 Dirty:1;
UINT32 PageSize:1; // It is PageAttribute:1 for 4K page entry
UINT32 Global:1;
UINT32 Ignored_9:1;
UINT32 ExtendedAccessed:1;
UINT32 Ignored_11:1;
// NOTE: There is PageAttribute:1 as bit12 for 1G page entry and 2M page entry
UINT32 AddressLo:20;
UINT32 AddressHi:20;
UINT32 Ignored_52:11;
UINT32 ExecuteDisable:1;
} Bits;
UINT64 Uint64;
} VTD_FIRST_LEVEL_PAGING_ENTRY;
typedef union {
struct {
UINT32 Read:1;
UINT32 Write:1;
UINT32 Execute:1;
UINT32 ExtendedMemoryType:3;
UINT32 IgnorePAT:1;
UINT32 PageSize:1;
UINT32 Ignored_8:3;
UINT32 Snoop:1;
UINT32 AddressLo:20;
UINT32 AddressHi:20;
UINT32 Ignored_52:10;
UINT32 TransientMapping:1;
UINT32 Ignored_63:1;
} Bits;
UINT64 Uint64;
} VTD_SECOND_LEVEL_PAGING_ENTRY;
//
// Register Descriptions
//
#define R_VER_REG 0x00
#define R_CAP_REG 0x08
#define B_CAP_REG_RWBF BIT4
#define R_ECAP_REG 0x10
#define R_GCMD_REG 0x18
#define B_GMCD_REG_WBF BIT27
#define B_GMCD_REG_SRTP BIT30
#define B_GMCD_REG_TE BIT31
#define R_GSTS_REG 0x1C
#define B_GSTS_REG_WBF BIT27
#define B_GSTS_REG_RTPS BIT30
#define B_GSTS_REG_TE BIT31
#define R_RTADDR_REG 0x20
#define R_CCMD_REG 0x28
#define B_CCMD_REG_CIRG_MASK (BIT62|BIT61)
#define V_CCMD_REG_CIRG_GLOBAL BIT61
#define V_CCMD_REG_CIRG_DOMAIN BIT62
#define V_CCMD_REG_CIRG_DEVICE (BIT62|BIT61)
#define B_CCMD_REG_ICC BIT63
#define R_FSTS_REG 0x34
#define R_FECTL_REG 0x38
#define R_FEDATA_REG 0x3C
#define R_FEADDR_REG 0x40
#define R_FEUADDR_REG 0x44
#define R_AFLOG_REG 0x58
#define R_IVA_REG 0x00 // + IRO
#define B_IVA_REG_AM_MASK (BIT0|BIT1|BIT2|BIT3|BIT4|BIT5)
#define B_IVA_REG_AM_4K 0 // 1 page
#define B_IVA_REG_AM_2M 9 // 2M page
#define B_IVA_REG_IH BIT6
#define R_IOTLB_REG 0x08 // + IRO
#define B_IOTLB_REG_IIRG_MASK (BIT61|BIT60)
#define V_IOTLB_REG_IIRG_GLOBAL BIT60
#define V_IOTLB_REG_IIRG_DOMAIN BIT61
#define V_IOTLB_REG_IIRG_PAGE (BIT61|BIT60)
#define B_IOTLB_REG_IVT BIT63
#define R_FRCD_REG 0x00 // + FRO
#define R_PMEN_ENABLE_REG 0x64
#define R_PMEN_LOW_BASE_REG 0x68
#define R_PMEN_LOW_LIMITE_REG 0x6C
#define R_PMEN_HIGH_BASE_REG 0x70
#define R_PMEN_HIGH_LIMITE_REG 0x78
typedef union {
struct {
UINT8 ND:3; // Number of domains supported
UINT8 AFL:1; // Advanced Fault Logging
UINT8 RWBF:1; // Required Write-Buffer Flushing
UINT8 PLMR:1; // Protected Low-Memory Region
UINT8 PHMR:1; // Protected High-Memory Region
UINT8 CM:1; // Caching Mode
UINT8 SAGAW:5; // Supported Adjusted Guest Address Widths
UINT8 Rsvd_13:3;
UINT8 MGAW:6; // Maximum Guest Address Width
UINT8 ZLR:1; // Zero Length Read
UINT8 Rsvd_23:1;
UINT16 FRO:10; // Fault-recording Register offset
UINT16 SLLPS:4; // Second Level Large Page Support
UINT16 Rsvd_38:1;
UINT16 PSI:1; // Page Selective Invalidation
UINT8 NFR:8; // Number of Fault-recording Registers
UINT8 MAMV:6; // Maximum Address Mask Value
UINT8 DWD:1; // Write Draining
UINT8 DRD:1; // Read Draining
UINT8 FL1GP:1; // First Level 1-GByte Page Support
UINT8 Rsvd_57:2;
UINT8 PI:1; // Posted Interrupts Support
UINT8 Rsvd_60:4;
} Bits;
UINT64 Uint64;
} VTD_CAP_REG;
typedef union {
struct {
UINT8 C:1; // Page-walk Coherency
UINT8 QI:1; // Queued Invalidation support
UINT8 DT:1; // Device-TLB support
UINT8 IR:1; // Interrupt Remapping support
UINT8 EIM:1; // Extended Interrupt Mode
UINT8 Rsvd_5:1;
UINT8 PT:1; // Pass Through
UINT8 SC:1; // Snoop Control
UINT16 IRO:10; // IOTLB Register Offset
UINT16 Rsvd_18:2;
UINT16 MHMV:4; // Maximum Handle Mask Value
UINT8 ECS:1; // Extended Context Support
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 PRS:1; // Page Request Support
UINT8 ERS:1; // Execute Request Support
UINT8 SRS:1; // Supervisor Request Support
UINT32 Rsvd_32:1;
UINT32 NWFS:1; // No Write Flag Support
UINT32 EAFS:1; // Extended Accessed Flag Support
UINT32 PSS:5; // PASID Size Supported
UINT32 Rsvd_40:24;
} Bits;
UINT64 Uint64;
} VTD_ECAP_REG;
typedef union {
struct {
UINT32 Rsvd_0:12;
UINT32 FILo:20; // FaultInfo
UINT32 FIHi:32; // FaultInfo
UINT32 SID:16; // Source Identifier
UINT32 Rsvd_80:13;
UINT32 PRIV:1; // Privilege Mode Requested
UINT32 EXE:1; // Execute Permission Requested
UINT32 PP:1; // PASID Present
UINT32 FR:8; // Fault Reason
UINT32 PV:20; // PASID Value
UINT32 AT:2; // Address Type
UINT32 T:1; // Type (0: Write, 1: Read)
UINT32 F:1; // Fault
} Bits;
UINT64 Uint64[2];
} VTD_FRCD_REG;
typedef union {
struct {
UINT8 Function:3;
UINT8 Device:5;
UINT8 Bus;
} Bits;
struct {
UINT8 ContextIndex;
UINT8 RootIndex;
} Index;
UINT16 Uint16;
} VTD_SOURCE_ID;
#pragma pack()
#endif

View File

@ -1,33 +0,0 @@
/** @file
Microcode flash device access library.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __MICROCODE_FLASH_ACCESS_LIB_H__
#define __MICROCODE_FLASH_ACCESS_LIB_H__
/**
Perform microcode write opreation.
@param[in] FlashAddress The address of flash device to be accessed.
@param[in] Buffer The pointer to the data buffer.
@param[in] Length The length of data buffer in bytes.
@retval EFI_SUCCESS The operation returns successfully.
@retval EFI_WRITE_PROTECTED The flash device is read only.
@retval EFI_UNSUPPORTED The flash device access is unsupported.
@retval EFI_INVALID_PARAMETER The input parameter is not valid.
**/
EFI_STATUS
EFIAPI
MicrocodeFlashWrite (
IN EFI_PHYSICAL_ADDRESS FlashAddress,
IN VOID *Buffer,
IN UINTN Length
);
#endif

View File

@ -1,37 +0,0 @@
/** @file
The definition for VTD information PPI.
This is a lightweight VTd information report in PEI phase.
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __VTD_INFO_PPI_H__
#define __VTD_INFO_PPI_H__
#include <IndustryStandard/DmaRemappingReportingTable.h>
#define EDKII_VTD_INFO_PPI_GUID \
{ \
0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } \
}
//
// VTD info PPI just use same data structure as DMAR table.
//
// The reported information must include what is needed in PEI phase, e.g.
// the VTd engine (such as DRHD)
// the reserved DMA address in PEI for eary graphic (such as RMRR for graphic UMA)
//
// The reported information can be and might be a subset of full DMAR table, e.g.
// if some data is not avaiable (such as ANDD),
// if some data is not needed (such as RMRR for legacy USB).
//
typedef EFI_ACPI_DMAR_HEADER EDKII_VTD_INFO_PPI;
extern EFI_GUID gEdkiiVTdInfoPpiGuid;
#endif

View File

@ -1,143 +0,0 @@
/** @file
The definition for platform VTD policy.
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef __PLATFORM_VTD_POLICY_PROTOCOL_H__
#define __PLATFORM_VTD_POLICY_PROTOCOL_H__
#include <IndustryStandard/Vtd.h>
#include <IndustryStandard/DmaRemappingReportingTable.h>
#define EDKII_PLATFORM_VTD_POLICY_PROTOCOL_GUID \
{ \
0x3d17e448, 0x466, 0x4e20, { 0x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 } \
}
typedef struct _EDKII_PLATFORM_VTD_POLICY_PROTOCOL EDKII_PLATFORM_VTD_POLICY_PROTOCOL;
#define EDKII_PLATFORM_VTD_POLICY_PROTOCOL_REVISION 0x00010000
typedef struct {
UINT16 Segment;
VTD_SOURCE_ID SourceId;
} EDKII_PLATFORM_VTD_DEVICE_INFO;
/**
Get the VTD SourceId from the device handler.
This function is required for non PCI device handler.
Pseudo-algo in Intel VTd driver:
Status = PlatformGetVTdDeviceId ();
if (EFI_ERROR(Status)) {
if (DeviceHandle is PCI) {
Get SourceId from Bus/Device/Function
} else {
return EFI_UNSUPPORTED
}
}
Get VTd engine by Segment/Bus/Device/Function.
@param[in] This The protocol instance pointer.
@param[in] DeviceHandle Device Identifier in UEFI.
@param[out] DeviceInfo DeviceInfo for indentify the VTd engine in ACPI Table
and the VTd page entry.
@retval EFI_SUCCESS The VtdIndex and SourceId are returned.
@retval EFI_INVALID_PARAMETER DeviceHandle is not a valid handler.
@retval EFI_INVALID_PARAMETER DeviceInfo is NULL.
@retval EFI_NOT_FOUND The Segment or SourceId information is NOT found.
@retval EFI_UNSUPPORTED This function is not supported.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_PLATFORM_VTD_POLICY_GET_DEVICE_ID) (
IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL *This,
IN EFI_HANDLE DeviceHandle,
OUT EDKII_PLATFORM_VTD_DEVICE_INFO *DeviceInfo
);
#pragma pack(1)
typedef struct {
//
// The segment number of the device
//
UINT16 SegmentNumber;
//
// Device scope definition in DMAR table
//
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER DeviceScope;
//
// Pci path definition in DMAR table
//
//EFI_ACPI_DMAR_PCI_PATH PciPath[];
} EDKII_PLATFORM_VTD_DEVICE_SCOPE;
typedef struct {
UINT16 VendorId;
UINT16 DeviceId;
UINT8 RevisionId;
UINT16 SubsystemVendorId;
UINT16 SubsystemDeviceId;
} EDKII_PLATFORM_VTD_PCI_DEVICE_ID;
#define EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_END 0
#define EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE 1
#define EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID 2
typedef struct {
//
// EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_xxx defined above.
//
UINT8 Type;
//
// The length of the full data structure including EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO and Data.
//
UINT8 Length;
//
// Data can be EDKII_PLATFORM_VTD_DEVICE_SCOPE or EDKII_PLATFORM_VTD_PCI_DEVICE_ID
//
//UINT8 Data[Length - sizeof(EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO)];
} EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO;
#pragma pack()
/**
Get a list of the exception devices.
The VTd driver should always set ALLOW for the device in this list.
@param[in] This The protocol instance pointer.
@param[out] DeviceInfoCount The count of the list of DeviceInfo.
@param[out] DeviceInfo A callee allocated buffer to hold a list of DeviceInfo.
Each DeviceInfo pointer points to EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO.
@retval EFI_SUCCESS The DeviceInfoCount and DeviceInfo are returned.
@retval EFI_INVALID_PARAMETER DeviceInfoCount is NULL, or DeviceInfo is NULL.
@retval EFI_UNSUPPORTED This function is not supported.
**/
typedef
EFI_STATUS
(EFIAPI *EDKII_PLATFORM_VTD_POLICY_GET_EXCEPTION_DEVICE_LIST) (
IN EDKII_PLATFORM_VTD_POLICY_PROTOCOL *This,
OUT UINTN *DeviceInfoCount,
OUT VOID **DeviceInfo
);
struct _EDKII_PLATFORM_VTD_POLICY_PROTOCOL {
UINT64 Revision;
EDKII_PLATFORM_VTD_POLICY_GET_DEVICE_ID GetDeviceId;
EDKII_PLATFORM_VTD_POLICY_GET_EXCEPTION_DEVICE_LIST GetExceptionDeviceList;
};
extern EFI_GUID gEdkiiPlatformVTdPolicyProtocolGuid;
#endif

View File

@ -1,80 +0,0 @@
## @file
# IntelSilicon Package
#
# This package provides common open source Intel silicon modules.
#
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
DEC_SPECIFICATION = 0x00010005
PACKAGE_NAME = IntelSiliconPkg
PACKAGE_GUID = F7A58914-FA0E-4F71-BD6A-220FDF824A49
PACKAGE_VERSION = 0.1
[Includes]
Include
[LibraryClasses.IA32, LibraryClasses.X64]
## @libraryclass Provides services to access Microcode region on flash device.
#
MicrocodeFlashAccessLib|Include/Library/MicrocodeFlashAccessLib.h
[Guids]
## GUID for Package token space
# {A9F8D54E-1107-4F0A-ADD0-4587E7A4A735}
gIntelSiliconPkgTokenSpaceGuid = { 0xa9f8d54e, 0x1107, 0x4f0a, { 0xad, 0xd0, 0x45, 0x87, 0xe7, 0xa4, 0xa7, 0x35 } }
## HOB GUID to publish SMBIOS data records from PEI phase
# HOB data format is same as SMBIOS records defined in SMBIOS spec or OEM defined types
# Generic DXE Library / Driver can locate HOB(s) and add SMBIOS records into SMBIOS table
gIntelSmbiosDataHobGuid = { 0x798e722e, 0x15b2, 0x4e13, { 0x8a, 0xe9, 0x6b, 0xa3, 0x0f, 0xf7, 0xf1, 0x67 }}
## Include/Guid/MicrocodeFmp.h
gMicrocodeFmpImageTypeIdGuid = { 0x96d4fdcd, 0x1502, 0x424d, { 0x9d, 0x4c, 0x9b, 0x12, 0xd2, 0xdc, 0xae, 0x5c } }
[Ppis]
gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } }
[Protocols]
gEdkiiPlatformVTdPolicyProtocolGuid = { 0x3d17e448, 0x466, 0x4e20, { 0x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }}
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Error code for VTd error.<BR><BR>
# EDKII_ERROR_CODE_VTD_ERROR = (EFI_IO_BUS_UNSPECIFIED | (EFI_OEM_SPECIFIC | 0x00000000)) = 0x02008000<BR>
# @Prompt Error code for VTd error.
gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError|0x02008000|UINT32|0x00000005
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## This is the GUID of the FFS which contains the Graphics Video BIOS Table (VBT)
# The VBT content is stored as a RAW section which is consumed by GOP PEI/UEFI driver.
# The default GUID can be updated by patching or runtime if platform support multiple VBT configurations.
# @Prompt GUID of the FFS which contains the Graphics Video BIOS Table (VBT)
# { 0x56752da9, 0xde6b, 0x4895, 0x88, 0x19, 0x19, 0x45, 0xb6, 0xb7, 0x6c, 0x22 }
gIntelSiliconPkgTokenSpaceGuid.PcdIntelGraphicsVbtFileGuid|{ 0xa9, 0x2d, 0x75, 0x56, 0x6b, 0xde, 0x95, 0x48, 0x88, 0x19, 0x19, 0x45, 0xb6, 0xb7, 0x6c, 0x22 }|VOID*|0x00000001
## The mask is used to control VTd behavior.<BR><BR>
# BIT0: Enable IOMMU during boot (If DMAR table is installed in DXE. If VTD_INFO_PPI is installed in PEI.)
# BIT1: Enable IOMMU when transfer control to OS (ExitBootService in normal boot. EndOfPEI in S3)
# BIT2: Force no IOMMU access attribute request recording before DMAR table is installed.
# @Prompt The policy for VTd driver behavior.
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask|1|UINT8|0x00000002
## Declares VTd PEI DMA buffer size.<BR><BR>
# When this PCD value is referred by platform to calculate the required
# memory size for PEI (InstallPeiMemory), the PMR alignment requirement
# needs be considered to be added with this PCD value for alignment
# adjustment need by AllocateAlignedPages.
# @Prompt The VTd PEI DMA buffer size.
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSize|0x00400000|UINT32|0x00000003
## Declares VTd PEI DMA buffer size for S3.<BR><BR>
# When this PCD value is referred by platform to calculate the required
# memory size for PEI S3 (InstallPeiMemory), the PMR alignment requirement
# needs be considered to be added with this PCD value for alignment
# adjustment need by AllocateAlignedPages.
# @Prompt The VTd PEI DMA buffer size for S3.
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3|0x00200000|UINT32|0x00000004

View File

@ -1,86 +0,0 @@
## @file
# This package provides common open source Intel silicon modules.
#
# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
PLATFORM_NAME = IntelSiliconPkg
PLATFORM_GUID = 9B96228E-1155-4967-8E16-D0ED8E1B4297
PLATFORM_VERSION = 0.1
DSC_SPECIFICATION = 0x00010005
OUTPUT_DIRECTORY = Build/IntelSiliconPkg
SUPPORTED_ARCHITECTURES = IA32|X64
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
MicrocodeFlashAccessLib|IntelSiliconPkg/Feature/Capsule/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
[LibraryClasses.common.PEIM]
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
[LibraryClasses.common.DXE_DRIVER]
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
###################################################################################################
#
# Components Section - list of the modules and components that will be processed by compilation
# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
#
# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
# into firmware volume images. This section is just a list of modules to compile from
# source into UEFI-compliant binaries.
# It is the FDF file that contains information on combining binary files into firmware
# volume images, whose concept is beyond UEFI and is described in PI specification.
# Binary modules do not need to be listed in this section, as they should be
# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
# Logo (Logo.bmp), and etc.
# There may also be modules listed in this section that are not required in the FDF file,
# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
# generated for it, but the binary will not be put into any firmware volume.
#
###################################################################################################
[Components]
IntelSiliconPkg/Library/DxeSmbiosDataHobLib/DxeSmbiosDataHobLib.inf
IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
IntelSiliconPkg/Feature/VTd/PlatformVTdSampleDxe/PlatformVTdSampleDxe.inf
IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
IntelSiliconPkg/Feature/Capsule/MicrocodeUpdateDxe/MicrocodeUpdateDxe.inf
IntelSiliconPkg/Feature/Capsule/Library/MicrocodeFlashAccessLibNull/MicrocodeFlashAccessLibNull.inf
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES

View File

@ -1,81 +0,0 @@
/** @file
Library to add SMBIOS data records from HOB to SMBIOS table.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Specification Reference:
System Management BIOS (SMBIOS) Reference Specification v3.0.0
dated 2015-Feb-12 (DSP0134)
http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
**/
#include <IndustryStandard/SmBios.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/Smbios.h>
/**
Adds SMBIOS records to tables
@param[in] ImageHandle Image handle of this driver.
@param[in] SystemTable Global system service table.
@retval EFI_UNSUPPORTED - Could not locate SMBIOS protocol
@retval EFI_OUT_OF_RESOURCES - Failed to allocate memory for SMBIOS HOB type.
@retval EFI_SUCCESS - Successfully added SMBIOS records based on HOB.
**/
EFI_STATUS
EFIAPI
DxeSmbiosDataHobLibConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_PEI_HOB_POINTERS Hob;
EFI_SMBIOS_HANDLE SmbiosHandle;
EFI_SMBIOS_PROTOCOL *Smbios;
EFI_STATUS Status;
UINT8 *RecordPtr;
UINT16 RecordCount;
RecordCount = 0;
DEBUG ((DEBUG_INFO, "Adding SMBIOS records from HOB..\n"));
Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID **)&Smbios);
if (Smbios == NULL) {
DEBUG ((DEBUG_WARN, "Can't locate SMBIOS protocol\n"));
return EFI_UNSUPPORTED;
}
///
/// Get SMBIOS HOB data (each hob contains one SMBIOS record)
///
for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
if ((GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_GUID_EXTENSION) && (CompareGuid (&Hob.Guid->Name, &gIntelSmbiosDataHobGuid))) {
RecordPtr = GET_GUID_HOB_DATA (Hob.Raw);
///
/// Add generic SMBIOS HOB to SMBIOS table
///
DEBUG ((DEBUG_VERBOSE, "Add SMBIOS record type: %x\n", ((EFI_SMBIOS_TABLE_HEADER *) RecordPtr)->Type));
SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
Status = Smbios->Add (Smbios, NULL, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) RecordPtr);
if (!EFI_ERROR (Status)) {
RecordCount++;
}
}
}
DEBUG ((DEBUG_INFO, "Found %d Records and added to SMBIOS table.\n", RecordCount));
return EFI_SUCCESS;
}

View File

@ -1,38 +0,0 @@
## @file
# Component INF file for the DxeSmbiosDataHob library.
#
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
[Defines]
INF_VERSION = 0x00010017
BASE_NAME = DxeSmbiosDataHobLib
FILE_GUID = AF55A9B6-2AE6-4B08-8CF7-750B7CBF49D7
MODULE_TYPE = DXE_DRIVER
LIBRARY_CLASS = NULL|DXE_DRIVER
CONSTRUCTOR = DxeSmbiosDataHobLibConstructor
[Packages]
MdePkg/MdePkg.dec
IntelSiliconPkg/IntelSiliconPkg.dec
[Sources]
DxeSmbiosDataHobLib.c
[LibraryClasses]
DebugLib
BaseMemoryLib
MemoryAllocationLib
BaseLib
HobLib
UefiLib
[Guids]
gIntelSmbiosDataHobGuid ## CONSUMES ## GUID
[Depex]
gEfiSmbiosProtocolGuid