/** 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; }
/** 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); } }
/** 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; }