mirror of https://github.com/acidanthera/audk.git
585 lines
18 KiB
C
585 lines
18 KiB
C
/** @file
|
|
|
|
Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php.
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include <Uefi.h>
|
|
#include <PiPei.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <IndustryStandard/Vtd.h>
|
|
#include <Ppi/VtdInfo.h>
|
|
|
|
#include "IntelVTdPmrPei.h"
|
|
|
|
/**
|
|
Dump DMAR DeviceScopeEntry.
|
|
|
|
@param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
|
|
**/
|
|
VOID
|
|
DumpDmarDeviceScopeEntry (
|
|
IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
|
|
)
|
|
{
|
|
UINTN PciPathNumber;
|
|
UINTN PciPathIndex;
|
|
EFI_ACPI_DMAR_PCI_PATH *PciPath;
|
|
|
|
if (DmarDeviceScopeEntry == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
" *************************************************************************\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" * DMA-Remapping Device Scope Entry Structure *\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" *************************************************************************\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
|
" DMAR Device Scope Entry address ...................... 0x%016lx\n" :
|
|
" DMAR Device Scope Entry address ...................... 0x%08x\n",
|
|
DmarDeviceScopeEntry
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Device Scope Entry Type ............................ 0x%02x\n",
|
|
DmarDeviceScopeEntry->Type
|
|
));
|
|
switch (DmarDeviceScopeEntry->Type) {
|
|
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
|
|
DEBUG ((DEBUG_INFO,
|
|
" PCI Endpoint Device\n"
|
|
));
|
|
break;
|
|
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
|
|
DEBUG ((DEBUG_INFO,
|
|
" PCI Sub-hierachy\n"
|
|
));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
DEBUG ((DEBUG_INFO,
|
|
" Length ............................................. 0x%02x\n",
|
|
DmarDeviceScopeEntry->Length
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Enumeration ID ..................................... 0x%02x\n",
|
|
DmarDeviceScopeEntry->EnumerationId
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Starting Bus Number ................................ 0x%02x\n",
|
|
DmarDeviceScopeEntry->StartBusNumber
|
|
));
|
|
|
|
PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
|
|
PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
|
|
for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
|
|
DEBUG ((DEBUG_INFO,
|
|
" Device ............................................. 0x%02x\n",
|
|
PciPath[PciPathIndex].Device
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Function ........................................... 0x%02x\n",
|
|
PciPath[PciPathIndex].Function
|
|
));
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
" *************************************************************************\n\n"
|
|
));
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Dump DMAR RMRR table.
|
|
|
|
@param[in] Rmrr DMAR RMRR table
|
|
**/
|
|
VOID
|
|
DumpDmarRmrr (
|
|
IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
|
|
)
|
|
{
|
|
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
|
|
INTN RmrrLen;
|
|
|
|
if (Rmrr == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
" ***************************************************************************\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" * Reserved Memory Region Reporting Structure *\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" ***************************************************************************\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
|
" RMRR address ........................................... 0x%016lx\n" :
|
|
" RMRR address ........................................... 0x%08x\n",
|
|
Rmrr
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Type ................................................. 0x%04x\n",
|
|
Rmrr->Header.Type
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Length ............................................... 0x%04x\n",
|
|
Rmrr->Header.Length
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Segment Number ....................................... 0x%04x\n",
|
|
Rmrr->SegmentNumber
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Reserved Memory Region Base Address .................. 0x%016lx\n",
|
|
Rmrr->ReservedMemoryRegionBaseAddress
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Reserved Memory Region Limit Address ................. 0x%016lx\n",
|
|
Rmrr->ReservedMemoryRegionLimitAddress
|
|
));
|
|
|
|
RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
|
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);
|
|
while (RmrrLen > 0) {
|
|
DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
|
|
RmrrLen -= DmarDeviceScopeEntry->Length;
|
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
" ***************************************************************************\n\n"
|
|
));
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Dump DMAR DRHD table.
|
|
|
|
@param[in] Drhd DMAR DRHD table
|
|
**/
|
|
VOID
|
|
DumpDmarDrhd (
|
|
IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
|
|
)
|
|
{
|
|
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
|
|
INTN DrhdLen;
|
|
|
|
if (Drhd == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
" ***************************************************************************\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" * DMA-Remapping Hardware Definition Structure *\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" ***************************************************************************\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
|
" DRHD address ........................................... 0x%016lx\n" :
|
|
" DRHD address ........................................... 0x%08x\n",
|
|
Drhd
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Type ................................................. 0x%04x\n",
|
|
Drhd->Header.Type
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Length ............................................... 0x%04x\n",
|
|
Drhd->Header.Length
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Flags ................................................ 0x%02x\n",
|
|
Drhd->Flags
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" INCLUDE_PCI_ALL .................................... 0x%02x\n",
|
|
Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Segment Number ....................................... 0x%04x\n",
|
|
Drhd->SegmentNumber
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Register Base Address ................................ 0x%016lx\n",
|
|
Drhd->RegisterBaseAddress
|
|
));
|
|
|
|
DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
|
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
|
|
while (DrhdLen > 0) {
|
|
DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
|
|
DrhdLen -= DmarDeviceScopeEntry->Length;
|
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
" ***************************************************************************\n\n"
|
|
));
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Dump DMAR ACPI table.
|
|
|
|
@param[in] Dmar DMAR ACPI table
|
|
**/
|
|
VOID
|
|
DumpAcpiDMAR (
|
|
IN EFI_ACPI_DMAR_HEADER *Dmar
|
|
)
|
|
{
|
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
|
INTN DmarLen;
|
|
|
|
if (Dmar == NULL) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Dump Dmar table
|
|
//
|
|
DEBUG ((DEBUG_INFO,
|
|
"*****************************************************************************\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
"* DMAR Table *\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
"*****************************************************************************\n"
|
|
));
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
|
"DMAR address ............................................. 0x%016lx\n" :
|
|
"DMAR address ............................................. 0x%08x\n",
|
|
Dmar
|
|
));
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
" Table Contents:\n"
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Host Address Width ................................... 0x%02x\n",
|
|
Dmar->HostAddressWidth
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" Flags ................................................ 0x%02x\n",
|
|
Dmar->Flags
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" INTR_REMAP ......................................... 0x%02x\n",
|
|
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
|
|
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
|
|
));
|
|
DEBUG ((DEBUG_INFO,
|
|
" DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",
|
|
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG
|
|
));
|
|
|
|
DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
|
|
while (DmarLen > 0) {
|
|
switch (DmarHeader->Type) {
|
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
|
DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
|
|
break;
|
|
case EFI_ACPI_DMAR_TYPE_RMRR:
|
|
DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
DmarLen -= DmarHeader->Length;
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO,
|
|
"*****************************************************************************\n\n"
|
|
));
|
|
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Get VTd engine number.
|
|
|
|
@param[in] AcpiDmarTable DMAR ACPI table
|
|
|
|
@return the VTd engine number.
|
|
**/
|
|
UINTN
|
|
GetVtdEngineNumber (
|
|
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
|
|
)
|
|
{
|
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
|
UINTN VtdIndex;
|
|
|
|
VtdIndex = 0;
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
|
switch (DmarHeader->Type) {
|
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
|
VtdIndex++;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
|
}
|
|
return VtdIndex ;
|
|
}
|
|
|
|
/**
|
|
Process DMAR DHRD table.
|
|
|
|
@param[in] VTdInfo The VTd engine context information.
|
|
@param[in] VtdIndex The index of VTd engine.
|
|
@param[in] DmarDrhd The DRHD table.
|
|
**/
|
|
VOID
|
|
ProcessDhrd (
|
|
IN VTD_INFO *VTdInfo,
|
|
IN UINTN VtdIndex,
|
|
IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
|
|
VTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
|
|
}
|
|
|
|
/**
|
|
Parse DMAR DRHD table.
|
|
|
|
@param[in] AcpiDmarTable DMAR ACPI table
|
|
|
|
@return EFI_SUCCESS The DMAR DRHD table is parsed.
|
|
**/
|
|
EFI_STATUS
|
|
ParseDmarAcpiTableDrhd (
|
|
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
|
|
)
|
|
{
|
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
|
UINTN VtdUnitNumber;
|
|
UINTN VtdIndex;
|
|
VTD_INFO *VTdInfo;
|
|
|
|
VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
|
|
if (VtdUnitNumber == 0) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
|
|
ASSERT(VTdInfo != NULL);
|
|
if (VTdInfo == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Initialize the engine mask to all.
|
|
//
|
|
VTdInfo->AcpiDmarTable = AcpiDmarTable;
|
|
VTdInfo->EngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
|
|
VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
|
|
VTdInfo->VTdEngineCount = VtdUnitNumber;
|
|
|
|
VtdIndex = 0;
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
|
switch (DmarHeader->Type) {
|
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
|
ASSERT (VtdIndex < VtdUnitNumber);
|
|
ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
|
|
VtdIndex++;
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
|
}
|
|
ASSERT (VtdIndex == VtdUnitNumber);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Return the VTd engine index according to the Segment and DevScopeEntry.
|
|
|
|
@param AcpiDmarTable DMAR ACPI table
|
|
@param Segment The segment of the VTd engine
|
|
@param DevScopeEntry The DevScopeEntry of the VTd engine
|
|
|
|
@return The VTd engine index according to the Segment and DevScopeEntry.
|
|
@retval -1 The VTd engine is not found.
|
|
**/
|
|
UINTN
|
|
GetVTdEngineFromDevScopeEntry (
|
|
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
|
|
IN UINT16 Segment,
|
|
IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
|
|
)
|
|
{
|
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
|
UINTN VtdIndex;
|
|
EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;
|
|
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;
|
|
|
|
VtdIndex = 0;
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
|
switch (DmarHeader->Type) {
|
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
|
DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
|
|
if (DmarDrhd->SegmentNumber != Segment) {
|
|
// Mismatch
|
|
break;
|
|
}
|
|
if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
|
|
((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
|
|
// No DevScopeEntry
|
|
// Do not handle PCI_ALL
|
|
break;
|
|
}
|
|
ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
|
|
while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
|
|
if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
|
|
(CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
|
|
return VtdIndex;
|
|
}
|
|
ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
|
}
|
|
return (UINTN)-1;
|
|
}
|
|
|
|
/**
|
|
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);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Parse DMAR DRHD table.
|
|
|
|
@param[in] VTdInfo The VTd engine context information.
|
|
**/
|
|
VOID
|
|
ParseDmarAcpiTableRmrr (
|
|
IN VTD_INFO *VTdInfo
|
|
)
|
|
{
|
|
EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
|
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
|
|
|
AcpiDmarTable = VTdInfo->AcpiDmarTable;
|
|
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
|
switch (DmarHeader->Type) {
|
|
case EFI_ACPI_DMAR_TYPE_RMRR:
|
|
ProcessRmrr (VTdInfo, (EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
|
}
|
|
}
|