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
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
(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
{\r
DEBUG ((DEBUG_INFO, "Vtd OnExitBootServices\n"));\r
DumpVtdRegsAll ();\r
- DisableDmar ();\r
- DumpVtdRegsAll ();\r
+\r
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {\r
+ DisableDmar ();\r
+ DumpVtdRegsAll ();\r
+ }\r
}\r
\r
/**\r