]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelSiliconPkg/IntelVTdDxe/DmaProtection.c
IntelSiliconPkg/IntelVTd: update PlatformVtdPolicy
[mirror_edk2.git] / IntelSiliconPkg / IntelVTdDxe / DmaProtection.c
index f0628b501a88a122330ee105406a1a016df70713..82ed4d2df28504f2c243db495d565793b26d589a 100644 (file)
@@ -151,6 +151,132 @@ ReturnUefiMemoryMap (
   return ;\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
+ScanBusCallbackAlwaysEnablePageAttribute (\r
+  IN VOID           *Context,\r
+  IN UINT16         Segment,\r
+  IN UINT8          Bus,\r
+  IN UINT8          Device,\r
+  IN UINT8          Function\r
+  )\r
+{\r
+  VTD_SOURCE_ID           SourceId;\r
+  EFI_STATUS              Status;\r
+\r
+  SourceId.Bits.Bus = Bus;\r
+  SourceId.Bits.Device = Device;\r
+  SourceId.Bits.Function = Function;\r
+  Status = AlwaysEnablePageAttribute (Segment, SourceId);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Always enable the VTd page attribute for the device in the DeviceScope.\r
+\r
+  @param[in]  DeviceScope  the input device scope data structure\r
+\r
+  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device in the device scope.\r
+**/\r
+EFI_STATUS\r
+AlwaysEnablePageAttributeDeviceScope (\r
+  IN  EDKII_PLATFORM_VTD_DEVICE_SCOPE   *DeviceScope\r
+  )\r
+{\r
+  UINT8                             Bus;\r
+  UINT8                             Device;\r
+  UINT8                             Function;\r
+  VTD_SOURCE_ID                     SourceId;\r
+  UINT8                             SecondaryBusNumber;\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceScope->DeviceScope, &Bus, &Device, &Function);\r
+\r
+  if (DeviceScope->DeviceScope.Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE) {\r
+    //\r
+    // Need scan the bridge and add all devices.\r
+    //\r
+    SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DeviceScope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
+    Status = ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusNumber, ScanBusCallbackAlwaysEnablePageAttribute);\r
+    return Status;\r
+  } else {\r
+    SourceId.Bits.Bus      = Bus;\r
+    SourceId.Bits.Device   = Device;\r
+    SourceId.Bits.Function = Function;\r
+    Status = AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, SourceId);\r
+    return Status;\r
+  }\r
+}\r
+\r
+/**\r
+  Always enable the VTd page attribute for the device matching DeviceId.\r
+\r
+  @param[in]  PciDeviceId  the input PCI device ID\r
+\r
+  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device matching DeviceId.\r
+**/\r
+EFI_STATUS\r
+AlwaysEnablePageAttributePciDeviceId (\r
+  IN  EDKII_PLATFORM_VTD_PCI_DEVICE_ID   *PciDeviceId\r
+  )\r
+{\r
+  UINTN            VtdIndex;\r
+  UINTN            PciIndex;\r
+  PCI_DEVICE_DATA  *PciDeviceData;\r
+  EFI_STATUS       Status;\r
+\r
+  for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {\r
+    for (PciIndex = 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; PciIndex++) {\r
+      PciDeviceData = &mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[PciIndex];\r
+\r
+      if (((PciDeviceId->VendorId == 0xFFFF) || (PciDeviceId->VendorId == PciDeviceData->PciDeviceId.VendorId)) &&\r
+          ((PciDeviceId->DeviceId == 0xFFFF) || (PciDeviceId->DeviceId == PciDeviceData->PciDeviceId.DeviceId)) &&\r
+          ((PciDeviceId->RevisionId == 0xFF) || (PciDeviceId->RevisionId == PciDeviceData->PciDeviceId.RevisionId)) &&\r
+          ((PciDeviceId->SubsystemVendorId == 0xFFFF) || (PciDeviceId->SubsystemVendorId == PciDeviceData->PciDeviceId.SubsystemVendorId)) &&\r
+          ((PciDeviceId->SubsystemDeviceId == 0xFFFF) || (PciDeviceId->SubsystemDeviceId == PciDeviceData->PciDeviceId.SubsystemDeviceId)) ) {\r
+        Status = AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex].Segment, PciDeviceData->PciSourceId);\r
+        if (EFI_ERROR(Status)) {\r
+          continue;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Always enable the VTd page attribute for the device.\r
+\r
+  @param[in]  DeviceInfo  the exception device information\r
+\r
+  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device in the device info.\r
+**/\r
+EFI_STATUS\r
+AlwaysEnablePageAttributeExceptionDeviceInfo (\r
+  IN  EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO   *DeviceInfo\r
+  )\r
+{\r
+  switch (DeviceInfo->Type) {\r
+  case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:\r
+    return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1));\r
+  case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:\r
+    return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1));\r
+  default:\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+}\r
+\r
 /**\r
   Initialize platform VTd policy.\r
 **/\r
@@ -159,10 +285,11 @@ InitializePlatformVTdPolicy (
   VOID\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  UINTN                             DeviceInfoCount;\r
-  EDKII_PLATFORM_VTD_DEVICE_INFO    *DeviceInfo;\r
-  UINTN                             Index;\r
+  EFI_STATUS                               Status;\r
+  UINTN                                    DeviceInfoCount;\r
+  VOID                                     *DeviceInfo;\r
+  EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;\r
+  UINTN                                    Index;\r
 \r
   //\r
   // It is optional.\r
@@ -173,10 +300,16 @@ InitializePlatformVTdPolicy (
                   (VOID **)&mPlatformVTdPolicy\r
                   );\r
   if (!EFI_ERROR(Status)) {\r
+    DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));\r
     Status = mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPolicy, &DeviceInfoCount, &DeviceInfo);\r
     if (!EFI_ERROR(Status)) {\r
+      ThisDeviceInfo = DeviceInfo;\r
       for (Index = 0; Index < DeviceInfoCount; Index++) {\r
-        AlwaysEnablePageAttribute (DeviceInfo[Index].Segment, DeviceInfo[Index].SourceId);\r
+        if (ThisDeviceInfo->Type == EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_END) {\r
+          break;\r
+        }\r
+        AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);\r
+        ThisDeviceInfo = (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo->Length);\r
       }\r
       FreePool (DeviceInfo);\r
     }\r