mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
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:
parent
370f16c548
commit
77ff7d6aa2
@ -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;
|
||||
}
|
@ -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
|
@ -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."
|
||||
|
@ -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
|
@ -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
|
@ -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`
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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`
|
||||
|
||||
|
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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
|
||||
|
@ -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."
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ;
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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."
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
@ -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"));
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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."
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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 ;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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."
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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."
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user