+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#ifndef _DMAR_PROTECTION_H_\r
-#define _DMAR_PROTECTION_H_\r
-\r
-#include <Uefi.h>\r
-#include <PiDxe.h>\r
-\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/PciSegmentLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/CacheMaintenanceLib.h>\r
-#include <Library/PerformanceLib.h>\r
-#include <Library/PrintLib.h>\r
-\r
-#include <Guid/EventGroup.h>\r
-#include <Guid/Acpi.h>\r
-\r
-#include <Protocol/DxeSmmReadyToLock.h>\r
-#include <Protocol/PciRootBridgeIo.h>\r
-#include <Protocol/PciIo.h>\r
-#include <Protocol/PciEnumerationComplete.h>\r
-#include <Protocol/AcpiSystemDescriptionTable.h>\r
-#include <Protocol/PlatformVtdPolicy.h>\r
-#include <Protocol/IoMmu.h>\r
-\r
-#include <IndustryStandard/Pci.h>\r
-#include <IndustryStandard/DmaRemappingReportingTable.h>\r
-#include <IndustryStandard/Vtd.h>\r
-\r
-#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32))\r
-\r
-#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (~((Alignment) - 1)))\r
-#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))\r
-\r
-//\r
-// This is the initial max PCI DATA number.\r
-// The number may be enlarged later.\r
-//\r
-#define MAX_VTD_PCI_DATA_NUMBER 0x100\r
-\r
-typedef struct {\r
- UINT8 DeviceType;\r
- VTD_SOURCE_ID PciSourceId;\r
- EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId;\r
- // for statistic analysis\r
- UINTN AccessCount;\r
-} PCI_DEVICE_DATA;\r
-\r
-typedef struct {\r
- BOOLEAN IncludeAllFlag;\r
- UINTN PciDeviceDataNumber;\r
- UINTN PciDeviceDataMaxNumber;\r
- PCI_DEVICE_DATA *PciDeviceData;\r
-} PCI_DEVICE_INFORMATION;\r
-\r
-typedef struct {\r
- UINTN VtdUnitBaseAddress;\r
- UINT16 Segment;\r
- VTD_CAP_REG CapReg;\r
- VTD_ECAP_REG ECapReg;\r
- VTD_ROOT_ENTRY *RootEntryTable;\r
- VTD_EXT_ROOT_ENTRY *ExtRootEntryTable;\r
- VTD_SECOND_LEVEL_PAGING_ENTRY *FixedSecondLevelPagingEntry;\r
- BOOLEAN HasDirtyContext;\r
- BOOLEAN HasDirtyPages;\r
- PCI_DEVICE_INFORMATION PciDeviceInfo;\r
-} VTD_UNIT_INFORMATION;\r
-\r
-/**\r
- The scan bus callback function.\r
-\r
- It is called in PCI bus scan for each PCI device under the bus.\r
-\r
- @param[in] Context The context of the callback.\r
- @param[in] Segment The segment of the source.\r
- @param[in] Bus The bus of the source.\r
- @param[in] Device The device of the source.\r
- @param[in] Function The function of the source.\r
-\r
- @retval EFI_SUCCESS The specific PCI device is processed in the callback.\r
-**/\r
-typedef\r
-EFI_STATUS\r
-(EFIAPI *SCAN_BUS_FUNC_CALLBACK_FUNC) (\r
- IN VOID *Context,\r
- IN UINT16 Segment,\r
- IN UINT8 Bus,\r
- IN UINT8 Device,\r
- IN UINT8 Function\r
- );\r
-\r
-extern EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;\r
-\r
-extern UINT64 mVtdHostAddressWidthMask;\r
-extern UINTN mVtdUnitNumber;\r
-extern VTD_UNIT_INFORMATION *mVtdUnitInformation;\r
-\r
-extern UINT64 mBelow4GMemoryLimit;\r
-extern UINT64 mAbove4GMemoryLimit;\r
-\r
-extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;\r
-\r
-/**\r
- Prepare VTD configuration.\r
-**/\r
-VOID\r
-PrepareVtdConfig (\r
- VOID\r
- );\r
-\r
-/**\r
- Setup VTd translation table.\r
-\r
- @retval EFI_SUCCESS Setup translation table successfully.\r
- @retval EFI_OUT_OF_RESOURCE Setup translation table fail.\r
-**/\r
-EFI_STATUS\r
-SetupTranslationTable (\r
- VOID\r
- );\r
-\r
-/**\r
- Enable DMAR translation.\r
-\r
- @retval EFI_SUCCESS DMAR translation is enabled.\r
- @retval EFI_DEVICE_ERROR DMAR translation is not enabled.\r
-**/\r
-EFI_STATUS\r
-EnableDmar (\r
- VOID\r
- );\r
-\r
-/**\r
- Disable DMAR translation.\r
-\r
- @retval EFI_SUCCESS DMAR translation is disabled.\r
- @retval EFI_DEVICE_ERROR DMAR translation is not disabled.\r
-**/\r
-EFI_STATUS\r
-DisableDmar (\r
- VOID\r
- );\r
-\r
-/**\r
- Invalid VTd global IOTLB.\r
-\r
- @param[in] VtdIndex The index of VTd engine.\r
-\r
- @retval EFI_SUCCESS VTd global IOTLB is invalidated.\r
- @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.\r
-**/\r
-EFI_STATUS\r
-InvalidateVtdIOTLBGlobal (\r
- IN UINTN VtdIndex\r
- );\r
-\r
-/**\r
- Dump VTd registers.\r
-\r
- @param[in] VtdIndex The index of VTd engine.\r
-**/\r
-VOID\r
-DumpVtdRegs (\r
- IN UINTN VtdIndex\r
- );\r
-\r
-/**\r
- Dump VTd registers for all VTd engine.\r
-**/\r
-VOID\r
-DumpVtdRegsAll (\r
- VOID\r
- );\r
-\r
-/**\r
- Dump VTd capability registers.\r
-\r
- @param[in] CapReg The capability register.\r
-**/\r
-VOID\r
-DumpVtdCapRegs (\r
- IN VTD_CAP_REG *CapReg\r
- );\r
-\r
-/**\r
- Dump VTd extended capability registers.\r
-\r
- @param[in] ECapReg The extended capability register.\r
-**/\r
-VOID\r
-DumpVtdECapRegs (\r
- IN VTD_ECAP_REG *ECapReg\r
- );\r
-\r
-/**\r
- Register PCI device to VTd engine.\r
-\r
- @param[in] VtdIndex The index of VTd engine.\r
- @param[in] Segment The segment of the source.\r
- @param[in] SourceId The SourceId of the source.\r
- @param[in] DeviceType The DMAR device scope type.\r
- @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered.\r
- FALSE: SUCCESS will be returned if the PCI device is registered.\r
-\r
- @retval EFI_SUCCESS The PCI device is registered.\r
- @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.\r
- @retval EFI_ALREADY_STARTED The device is already registered.\r
-**/\r
-EFI_STATUS\r
-RegisterPciDevice (\r
- IN UINTN VtdIndex,\r
- IN UINT16 Segment,\r
- IN VTD_SOURCE_ID SourceId,\r
- IN UINT8 DeviceType,\r
- IN BOOLEAN CheckExist\r
- );\r
-\r
-/**\r
- The scan bus callback function to always enable page attribute.\r
-\r
- @param[in] Context The context of the callback.\r
- @param[in] Segment The segment of the source.\r
- @param[in] Bus The bus of the source.\r
- @param[in] Device The device of the source.\r
- @param[in] Function The function of the source.\r
-\r
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-ScanBusCallbackRegisterPciDevice (\r
- IN VOID *Context,\r
- IN UINT16 Segment,\r
- IN UINT8 Bus,\r
- IN UINT8 Device,\r
- IN UINT8 Function\r
- );\r
-\r
-/**\r
- Scan PCI bus and invoke callback function for each PCI devices under the bus.\r
-\r
- @param[in] Context The context of the callback function.\r
- @param[in] Segment The segment of the source.\r
- @param[in] Bus The bus of the source.\r
- @param[in] Callback The callback function in PCI scan.\r
-\r
- @retval EFI_SUCCESS The PCI devices under the bus are scaned.\r
-**/\r
-EFI_STATUS\r
-ScanPciBus (\r
- IN VOID *Context,\r
- IN UINT16 Segment,\r
- IN UINT8 Bus,\r
- IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback\r
- );\r
-\r
-/**\r
- Dump the PCI device information managed by this VTd engine.\r
-\r
- @param[in] VtdIndex The index of VTd engine.\r
-**/\r
-VOID\r
-DumpPciDeviceInfo (\r
- IN UINTN VtdIndex\r
- );\r
-\r
-/**\r
- Find the VTd index by the Segment and SourceId.\r
-\r
- @param[in] Segment The segment of the source.\r
- @param[in] SourceId The SourceId of the source.\r
- @param[out] ExtContextEntry The ExtContextEntry of the source.\r
- @param[out] ContextEntry The ContextEntry of the source.\r
-\r
- @return The index of the VTd engine.\r
- @retval (UINTN)-1 The VTd engine is not found.\r
-**/\r
-UINTN\r
-FindVtdIndexByPciDevice (\r
- IN UINT16 Segment,\r
- IN VTD_SOURCE_ID SourceId,\r
- OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,\r
- OUT VTD_CONTEXT_ENTRY **ContextEntry\r
- );\r
-\r
-/**\r
- Get the DMAR ACPI table.\r
-\r
- @retval EFI_SUCCESS The DMAR ACPI table is got.\r
- @retval EFI_NOT_FOUND The DMAR ACPI table is not found.\r
-**/\r
-EFI_STATUS\r
-GetDmarAcpiTable (\r
- VOID\r
- );\r
-\r
-/**\r
- Parse DMAR DRHD table.\r
-\r
- @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
-**/\r
-EFI_STATUS\r
-ParseDmarAcpiTableDrhd (\r
- VOID\r
- );\r
-\r
-/**\r
- Parse DMAR RMRR table.\r
-\r
- @return EFI_SUCCESS The DMAR RMRR table is parsed.\r
-**/\r
-EFI_STATUS\r
-ParseDmarAcpiTableRmrr (\r
- VOID\r
- );\r
-\r
-/**\r
- Dump DMAR context entry table.\r
-\r
- @param[in] RootEntry DMAR root entry.\r
-**/\r
-VOID\r
-DumpDmarContextEntryTable (\r
- IN VTD_ROOT_ENTRY *RootEntry\r
- );\r
-\r
-/**\r
- Dump DMAR extended context entry table.\r
-\r
- @param[in] ExtRootEntry DMAR extended root entry.\r
-**/\r
-VOID\r
-DumpDmarExtContextEntryTable (\r
- IN VTD_EXT_ROOT_ENTRY *ExtRootEntry\r
- );\r
-\r
-/**\r
- Dump DMAR second level paging entry.\r
-\r
- @param[in] SecondLevelPagingEntry The second level paging entry.\r
-**/\r
-VOID\r
-DumpSecondLevelPagingEntry (\r
- IN VOID *SecondLevelPagingEntry\r
- );\r
-\r
-/**\r
- Set VTd attribute for a system memory.\r
-\r
- @param[in] VtdIndex The index used to identify a VTd engine.\r
- @param[in] DomainIdentifier The domain ID of the source.\r
- @param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.\r
- @param[in] BaseAddress The base of device memory address to be used as the DMA memory.\r
- @param[in] Length The length of device memory address to be used as the DMA memory.\r
- @param[in] IoMmuAccess The IOMMU access.\r
-\r
- @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.\r
- @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.\r
- @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.\r
- @retval EFI_INVALID_PARAMETER Length is 0.\r
- @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.\r
- @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.\r
- @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.\r
- @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.\r
-**/\r
-EFI_STATUS\r
-SetPageAttribute (\r
- IN UINTN VtdIndex,\r
- IN UINT16 DomainIdentifier,\r
- IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,\r
- IN UINT64 BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 IoMmuAccess\r
- );\r
-\r
-/**\r
- Set VTd attribute for a system memory.\r
-\r
- @param[in] Segment The Segment used to identify a VTd engine.\r
- @param[in] SourceId The SourceId used to identify a VTd engine and table entry.\r
- @param[in] BaseAddress The base of device memory address to be used as the DMA memory.\r
- @param[in] Length The length of device memory address to be used as the DMA memory.\r
- @param[in] IoMmuAccess The IOMMU access.\r
-\r
- @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.\r
- @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.\r
- @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.\r
- @retval EFI_INVALID_PARAMETER Length is 0.\r
- @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.\r
- @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.\r
- @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.\r
- @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.\r
-**/\r
-EFI_STATUS\r
-SetAccessAttribute (\r
- IN UINT16 Segment,\r
- IN VTD_SOURCE_ID SourceId,\r
- IN UINT64 BaseAddress,\r
- IN UINT64 Length,\r
- IN UINT64 IoMmuAccess\r
- );\r
-\r
-/**\r
- Return the index of PCI data.\r
-\r
- @param[in] VtdIndex The index used to identify a VTd engine.\r
- @param[in] Segment The Segment used to identify a VTd engine.\r
- @param[in] SourceId The SourceId used to identify a VTd engine and table entry.\r
-\r
- @return The index of the PCI data.\r
- @retval (UINTN)-1 The PCI data is not found.\r
-**/\r
-UINTN\r
-GetPciDataIndex (\r
- IN UINTN VtdIndex,\r
- IN UINT16 Segment,\r
- IN VTD_SOURCE_ID SourceId\r
- );\r
-\r
-/**\r
- Dump VTd registers if there is error.\r
-**/\r
-VOID\r
-DumpVtdIfError (\r
- VOID\r
- );\r
-\r
-/**\r
- Initialize platform VTd policy.\r
-**/\r
-VOID\r
-InitializePlatformVTdPolicy (\r
- VOID\r
- );\r
-\r
-/**\r
- Always enable the VTd page attribute for the device.\r
-\r
- @param[in] Segment The Segment used to identify a VTd engine.\r
- @param[in] SourceId The SourceId used to identify a VTd engine and table entry.\r
-\r
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.\r
-**/\r
-EFI_STATUS\r
-AlwaysEnablePageAttribute (\r
- IN UINT16 Segment,\r
- IN VTD_SOURCE_ID SourceId\r
- );\r
-\r
-/**\r
- Convert the DeviceHandle to SourceId and Segment.\r
-\r
- @param[in] DeviceHandle The device who initiates the DMA access request.\r
- @param[out] Segment The Segment used to identify a VTd engine.\r
- @param[out] SourceId The SourceId used to identify a VTd engine and table entry.\r
-\r
- @retval EFI_SUCCESS The Segment and SourceId are returned.\r
- @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.\r
- @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.\r
-**/\r
-EFI_STATUS\r
-DeviceHandleToSourceId (\r
- IN EFI_HANDLE DeviceHandle,\r
- OUT UINT16 *Segment,\r
- OUT VTD_SOURCE_ID *SourceId\r
- );\r
-\r
-/**\r
- Get device information from mapping.\r
-\r
- @param[in] Mapping The mapping.\r
- @param[out] DeviceAddress The device address of the mapping.\r
- @param[out] NumberOfPages The number of pages of the mapping.\r
-\r
- @retval EFI_SUCCESS The device information is returned.\r
- @retval EFI_INVALID_PARAMETER The mapping is invalid.\r
-**/\r
-EFI_STATUS\r
-GetDeviceInfoFromMapping (\r
- IN VOID *Mapping,\r
- OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
- OUT UINTN *NumberOfPages\r
- );\r
-\r
-/**\r
- Initialize DMA protection.\r
-**/\r
-VOID\r
-InitializeDmaProtection (\r
- VOID\r
- );\r
-\r
-/**\r
- Allocate zero pages.\r
-\r
- @param[in] Pages the number of pages.\r
-\r
- @return the page address.\r
- @retval NULL No resource to allocate pages.\r
-**/\r
-VOID *\r
-EFIAPI\r
-AllocateZeroPages (\r
- IN UINTN Pages\r
- );\r
-\r
-/**\r
- Flush VTD page table and context table memory.\r
-\r
- This action is to make sure the IOMMU engine can get final data in memory.\r
-\r
- @param[in] VtdIndex The index used to identify a VTd engine.\r
- @param[in] Base The base address of memory to be flushed.\r
- @param[in] Size The size of memory in bytes to be flushed.\r
-**/\r
-VOID\r
-FlushPageTableMemory (\r
- IN UINTN VtdIndex,\r
- IN UINTN Base,\r
- IN UINTN Size\r
- );\r
-\r
-/**\r
- Get PCI device information from DMAR DevScopeEntry.\r
-\r
- @param[in] Segment The segment number.\r
- @param[in] DmarDevScopeEntry DMAR DevScopeEntry\r
- @param[out] Bus The bus number.\r
- @param[out] Device The device number.\r
- @param[out] Function The function number.\r
-\r
- @retval EFI_SUCCESS The PCI device information is returned.\r
-**/\r
-EFI_STATUS\r
-GetPciBusDeviceFunction (\r
- IN UINT16 Segment,\r
- IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,\r
- OUT UINT8 *Bus,\r
- OUT UINT8 *Device,\r
- OUT UINT8 *Function\r
- );\r
-\r
-#endif\r