\r
EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;\r
\r
+VTD_ACCESS_REQUEST *mAccessRequest = NULL;\r
+UINTN mAccessRequestCount = 0;\r
+UINTN mAccessRequestMaxCount = 0;\r
+\r
+/**\r
+ Append VTd Access Request to global.\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
+**/\r
+EFI_STATUS\r
+RequestAccessAttribute (\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
+ VTD_ACCESS_REQUEST *NewAccessRequest;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Optimization for memory.\r
+ //\r
+ // If the last record is to IoMmuAccess=0,\r
+ // Check previous records and remove the matched entry.\r
+ //\r
+ if (IoMmuAccess == 0) {\r
+ for (Index = 0; Index < mAccessRequestCount; Index++) {\r
+ if ((mAccessRequest[Index].Segment == Segment) &&\r
+ (mAccessRequest[Index].SourceId.Uint16 == SourceId.Uint16) &&\r
+ (mAccessRequest[Index].BaseAddress == BaseAddress) &&\r
+ (mAccessRequest[Index].Length == Length) &&\r
+ (mAccessRequest[Index].IoMmuAccess != 0)) {\r
+ //\r
+ // Remove this record [Index].\r
+ // No need to add the new record.\r
+ //\r
+ if (Index != mAccessRequestCount - 1) {\r
+ CopyMem (\r
+ &mAccessRequest[Index],\r
+ &mAccessRequest[Index + 1],\r
+ sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index)\r
+ );\r
+ }\r
+ ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCESS_REQUEST));\r
+ mAccessRequestCount--;\r
+ return EFI_SUCCESS;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (mAccessRequestCount >= mAccessRequestMaxCount) {\r
+ NewAccessRequest = AllocateZeroPool (sizeof(*NewAccessRequest) * (mAccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));\r
+ if (NewAccessRequest == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ mAccessRequestMaxCount += MAX_VTD_ACCESS_REQUEST;\r
+ if (mAccessRequest != NULL) {\r
+ CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest) * mAccessRequestCount);\r
+ FreePool (mAccessRequest);\r
+ }\r
+ mAccessRequest = NewAccessRequest;\r
+ }\r
+\r
+ ASSERT (mAccessRequestCount < mAccessRequestMaxCount);\r
+\r
+ mAccessRequest[mAccessRequestCount].Segment = Segment;\r
+ mAccessRequest[mAccessRequestCount].SourceId = SourceId;\r
+ mAccessRequest[mAccessRequestCount].BaseAddress = BaseAddress;\r
+ mAccessRequest[mAccessRequestCount].Length = Length;\r
+ mAccessRequest[mAccessRequestCount].IoMmuAccess = IoMmuAccess;\r
+\r
+ mAccessRequestCount++;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Process Access Requests from before DMAR table is installed.\r
+\r
+**/\r
+VOID\r
+ProcessRequestedAccessAttribute (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+\r
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));\r
+\r
+ for (Index = 0; Index < mAccessRequestCount; Index++) {\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "PCI(S%x.B%x.D%x.F%x) ",\r
+ mAccessRequest[Index].Segment,\r
+ mAccessRequest[Index].SourceId.Bits.Bus,\r
+ mAccessRequest[Index].SourceId.Bits.Device,\r
+ mAccessRequest[Index].SourceId.Bits.Function\r
+ ));\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "(0x%lx~0x%lx) - %lx\n",\r
+ mAccessRequest[Index].BaseAddress,\r
+ mAccessRequest[Index].Length,\r
+ mAccessRequest[Index].IoMmuAccess\r
+ ));\r
+ Status = SetAccessAttribute (\r
+ mAccessRequest[Index].Segment,\r
+ mAccessRequest[Index].SourceId,\r
+ mAccessRequest[Index].BaseAddress,\r
+ mAccessRequest[Index].Length,\r
+ mAccessRequest[Index].IoMmuAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));\r
+ }\r
+ }\r
+\r
+ if (mAccessRequest != NULL) {\r
+ FreePool (mAccessRequest);\r
+ }\r
+ mAccessRequest = NULL;\r
+ mAccessRequestCount = 0;\r
+ mAccessRequestMaxCount = 0;\r
+\r
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));\r
+}\r
+\r
/**\r
return the UEFI memory information.\r
\r
\r
ParseDmarAcpiTableRmrr ();\r
\r
+ ProcessRequestedAccessAttribute ();\r
+\r
for (Index = 0; Index < mVtdUnitNumber; Index++) {\r
DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment));\r
if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {\r