Re: [edk2 2/2] MdePkg: add BaseSerialPortLibRiscVSbi
Sunil V L
Hi Andrei,
It is not just mLastGetChar but mHaveDbcn also will have the same issue
with XIP. So, I am wondering why not probe for the extension in every write
for the SecPei case? I understand the performance concerns but does it really
matter for debug output? I believe it is minor compared to the
flexibility it provides for not having a fixed serial port
implementation.
Thanks,
Sunil
toggle quoted message
Show quoted text
It is not just mLastGetChar but mHaveDbcn also will have the same issue
with XIP. So, I am wondering why not probe for the extension in every write
for the SecPei case? I understand the performance concerns but does it really
matter for debug output? I believe it is minor compared to the
flexibility it provides for not having a fixed serial port
implementation.
Thanks,
Sunil
On Wed, Mar 01, 2023 at 05:56:36PM +0000, Andrei Warkentin wrote:
Thanks... let me go a different route.
I'll have 1 more variant that can be used in classical SEC and PEI - only capable of output (input doesn't matter) and rename the one I already shared. I'll name these SecPeiSerialPortLibRiscVSbi and PrePiDxeSerialPortLibRiscVSbi, respectively.
Does this sound acceptable?
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@...>
Sent: Wednesday, March 1, 2023 11:51 AM
To: Warkentin, Andrei <andrei.warkentin@...>; devel@edk2.groups.io; kraxel@...
Cc: Daniel Schaefer <git@...>; Sunil V L <sunilvl@...>; Kinney, Michael D <michael.d.kinney@...>
Subject: RE: [edk2-devel] [edk2 2/2] MdePkg: add BaseSerialPortLibRiscVSbi
If a dependency on MdePkg\Include\Library\ BaseRiscVSbiLib.h and SBI services assumed memory is available and code loaded is loaded into RAM and not XIP, then BASE is ok for this component.
You may want to make sure the library class header file and INF file header for BaseRiscVSbiLib describe that environment assumption and the INF for BaseSerialPortLibRiscVSbi also describes that environment assumption.
Mike-----Original Message-----
From: Warkentin, Andrei <andrei.warkentin@...>
Sent: Wednesday, March 1, 2023 9:26 AM
To: Kinney, Michael D <michael.d.kinney@...>;
devel@edk2.groups.io; kraxel@...
Cc: Daniel Schaefer <git@...>; Sunil V L
<sunilvl@...>
Subject: RE: [edk2-devel] [edk2 2/2] MdePkg: add
BaseSerialPortLibRiscVSbi
Hi Michael,
What module type should I use instead? The reason being this
SerialPortLib implementation specifically fits into the class of UEFI
implementations, where RAM is always available (initialized by something else prior to Tiano) and non-const globals can be used (e.g. PrePi).
A
-----Original Message-----
From: Kinney, Michael D <michael.d.kinney@...>
Sent: Wednesday, March 1, 2023 10:56 AM
To: devel@edk2.groups.io; kraxel@...; Warkentin, Andrei
<andrei.warkentin@...>
Cc: Daniel Schaefer <git@...>; Sunil V L
<sunilvl@...>; Kinney, Michael D
<michael.d.kinney@...>
Subject: RE: [edk2-devel] [edk2 2/2] MdePkg: add
BaseSerialPortLibRiscVSbi
Using a global is not compatible with XIP code where only const globals are supported.
A module of type BASE is considered compatible with XIP components.
Mike-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Gerd
Hoffmann
Sent: Wednesday, March 1, 2023 1:07 AM
To: Warkentin, Andrei <andrei.warkentin@...>
Cc: devel@edk2.groups.io; Daniel Schaefer <git@...>;
Sunil V L <sunilvl@...>
Subject: Re: [edk2-devel] [edk2 2/2] MdePkg: add
BaseSerialPortLibRiscVSbi
On Wed, Mar 01, 2023 at 08:50:38AM +0000, Warkentin, Andrei wrote:The library caller could call Poll() first,Ah, Poll is part of the library API, not just an internal helper.
Ok, makes sense then.
series:
Acked-by: Gerd Hoffmann <kraxel@...>
take care,
Gerd
[PATCH v2] IntelSiliconPkg/Vtd: Add Vtd core drivers
Sheng Wei
Add 2 drivers (IntelVTdCorePei, IntelVTdCoreDxe)
for pre-boot DMA protection feature.
Signed-off-by: Sheng Wei <w.sheng@...>
Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Jenny Huang <jenny.huang@...>
Cc: Robert Kowalewski <robert.kowalewski@...>
---
.../Feature/VTd/IntelVTdCoreDxe/BmDma.c | 547 +++++
.../VTd/IntelVTdCoreDxe/DmaProtection.c | 703 +++++++
.../VTd/IntelVTdCoreDxe/DmaProtection.h | 658 ++++++
.../VTd/IntelVTdCoreDxe/DmarAcpiTable.c | 398 ++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.c | 787 +++++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.inf | 92 +
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.uni | 14 +
.../IntelVTdCoreDxe/IntelVTdCoreDxeExtra.uni | 14 +
.../Feature/VTd/IntelVTdCoreDxe/PciInfo.c | 419 ++++
.../VTd/IntelVTdCoreDxe/TranslationTable.c | 1112 ++++++++++
.../VTd/IntelVTdCoreDxe/TranslationTableEx.c | 108 +
.../Feature/VTd/IntelVTdCoreDxe/VtdReg.c | 757 +++++++
.../Feature/VTd/IntelVTdCorePei/DmarTable.c | 301 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.c | 1099 ++++++++++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.h | 272 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.inf | 70 +
.../VTd/IntelVTdCorePei/IntelVTdCorePei.uni | 14 +
.../IntelVTdCorePei/IntelVTdCorePeiExtra.uni | 14 +
.../VTd/IntelVTdCorePei/IntelVTdDmar.c | 727 +++++++
.../VTd/IntelVTdCorePei/TranslationTable.c | 926 +++++++++
.../Include/Guid/VtdLogDataHob.h | 151 ++
.../Include/Library/IntelVTdPeiDxeLib.h | 329 +++
.../IntelSiliconPkg/Include/Protocol/VtdLog.h | 59 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 21 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dsc | 1 +
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.c | 1819 +++++++++++++++++
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.inf | 30 +
.../IntelVTdPeiDxeLibExt.inf | 34 +
28 files changed, 11476 insertions(+)
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/BmDma.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmarAcpiTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxeExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/PciInfo.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTableEx.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/VtdReg.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/DmarTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePeiExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdDmar.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHo=
b.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdP=
eiDxeLib.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLibExt.inf
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDm=
a.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
new file mode 100644
index 000000000..41917a004
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
@@ -0,0 +1,547 @@
+/** @file=0D
+ BmDma related function=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+// TBD: May make it a policy=0D
+#define DMA_MEMORY_TOP MAX_UINTN=0D
+//#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL=0D
+=0D
+#define MAP_HANDLE_INFO_SIGNATURE SIGNATURE_32 ('H', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EFI_HANDLE DeviceHandle;=0D
+ UINT64 IoMmuAccess;=0D
+} MAP_HANDLE_INFO;=0D
+#define MAP_HANDLE_INFO_FROM_LINK(a) CR (a, MAP_HANDLE_INFO, Link, MAP_HAN=
DLE_INFO_SIGNATURE)=0D
+=0D
+#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EDKII_IOMMU_OPERATION Operation;=0D
+ UINTN NumberOfBytes;=0D
+ UINTN NumberOfPages;=0D
+ EFI_PHYSICAL_ADDRESS HostAddress;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ LIST_ENTRY HandleList;=0D
+} MAP_INFO;=0D
+#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)=0D
+=0D
+LIST_ENTRY gMaps =3D INITIALIZE_LIST_HEAD_VARIABLE(=
gMaps);=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ //=0D
+ // Find MapInfo according to DeviceAddress=0D
+ //=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo->DeviceAddress =3D=3D DeviceAddress) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapInfo =3D=3D NULL) || (MapInfo->DeviceAddress !=3D DeviceAddress)=
) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: DeviceAddress(0x%lx) =
- not found\n", DeviceAddress));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // Find MapHandleInfo according to DeviceHandle=0D
+ //=0D
+ MapHandleInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&MapInfo->HandleList)=0D
+ ; !IsNull (&MapInfo->HandleList, Link)=0D
+ ; Link =3D GetNextNode (&MapInfo->HandleList, Link)=0D
+ ) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (Link);=0D
+ if (MapHandleInfo->DeviceHandle =3D=3D DeviceHandle) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapHandleInfo !=3D NULL) && (MapHandleInfo->DeviceHandle =3D=3D Dev=
iceHandle)) {=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // No DeviceHandle=0D
+ // Initialize and insert the MAP_HANDLE_INFO structure=0D
+ //=0D
+ MapHandleInfo =3D AllocatePool (sizeof (MAP_HANDLE_INFO));=0D
+ if (MapHandleInfo =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: %r\n", EFI_OUT_OF_RES=
OURCES));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ MapHandleInfo->Signature =3D MAP_HANDLE_INFO_SIGNATURE;=0D
+ MapHandleInfo->DeviceHandle =3D DeviceHandle;=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ InsertTailList (&MapInfo->HandleList, &MapHandleInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+ MAP_INFO *MapInfo;=0D
+ EFI_PHYSICAL_ADDRESS DmaMemoryTop;=0D
+ BOOLEAN NeedRemap;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ if (NumberOfBytes =3D=3D NULL || DeviceAddress =3D=3D NULL ||=0D
+ Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: =3D=3D> 0x%08x - 0x%08x (%x)\n", HostA=
ddress, *NumberOfBytes, Operation));=0D
+=0D
+ //=0D
+ // Make sure that Operation is valid=0D
+ //=0D
+ if ((UINT32) Operation >=3D EdkiiIoMmuOperationMaximum) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ NeedRemap =3D FALSE;=0D
+ PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;=0D
+=0D
+ DmaMemoryTop =3D DMA_MEMORY_TOP;=0D
+=0D
+ //=0D
+ // Alignment check=0D
+ //=0D
+ if ((*NumberOfBytes !=3D ALIGN_VALUE(*NumberOfBytes, SIZE_4KB)) ||=0D
+ (PhysicalAddress !=3D ALIGN_VALUE(PhysicalAddress, SIZE_4KB))) {=0D
+ if ((Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer) ||=0D
+ (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) {=0D
+ //=0D
+ // The input buffer might be a subset from IoMmuAllocateBuffer.=0D
+ // Skip the check.=0D
+ //=0D
+ } else {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+ }=0D
+=0D
+ if ((PhysicalAddress + *NumberOfBytes) >=3D DMA_MEMORY_TOP) {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+=0D
+ if (((Operation !=3D EdkiiIoMmuOperationBusMasterRead64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterWrite64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) &&=0D
+ ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {=0D
+ //=0D
+ // If the root bridge or the device cannot handle performing DMA above=
=0D
+ // 4GB but any part of the DMA transfer being mapped is above 4GB, the=
n=0D
+ // map the DMA transfer to a buffer below 4GB.=0D
+ //=0D
+ NeedRemap =3D TRUE;=0D
+ DmaMemoryTop =3D MIN (DmaMemoryTop, SIZE_4GB - 1);=0D
+ }=0D
+=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64) {=0D
+ if (NeedRemap) {=0D
+ //=0D
+ // Common Buffer operations can not be remapped. If the common buff=
er=0D
+ // is above 4GB, then it is not possible to generate a mapping, so r=
eturn=0D
+ // an error.=0D
+ //=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is=
=0D
+ // called later.=0D
+ //=0D
+ MapInfo =3D AllocatePool (sizeof (MAP_INFO));=0D
+ if (MapInfo =3D=3D NULL) {=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_OUT_OF_RESOURCES));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the MAP_INFO structure=0D
+ //=0D
+ MapInfo->Signature =3D MAP_INFO_SIGNATURE;=0D
+ MapInfo->Operation =3D Operation;=0D
+ MapInfo->NumberOfBytes =3D *NumberOfBytes;=0D
+ MapInfo->NumberOfPages =3D EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes=
);=0D
+ MapInfo->HostAddress =3D PhysicalAddress;=0D
+ MapInfo->DeviceAddress =3D DmaMemoryTop;=0D
+ InitializeListHead(&MapInfo->HandleList);=0D
+=0D
+ //=0D
+ // Allocate a buffer below 4GB to map the transfer to.=0D
+ //=0D
+ if (NeedRemap) {=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ EfiBootServicesData,=0D
+ MapInfo->NumberOfPages,=0D
+ &MapInfo->DeviceAddress=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (MapInfo);=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+=0D
+ //=0D
+ // If this is a read operation from the Bus Master's point of view,=0D
+ // then copy the contents of the real buffer into the mapped buffer=0D
+ // so the Bus Master can read the contents of the real buffer.=0D
+ //=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterRead ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterRead64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+ } else {=0D
+ MapInfo->DeviceAddress =3D MapInfo->HostAddress;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ InsertTailList (&gMaps, &MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // The DeviceAddress is the address of the maped buffer below 4GB=0D
+ //=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ //=0D
+ // Return a pointer to the MAP_INFO structure in Mapping=0D
+ //=0D
+ *Mapping =3D MapInfo;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: 0x%08x - 0x%08x <=3D=3D\n", *DeviceAdd=
ress, *Mapping));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_MAP, (UINT64) (*DeviceAddress), (UINT64=
) Operation);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuUnmap: 0x%08x\n", Mapping));=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ RemoveEntryList (&MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // remove all nodes in MapInfo->HandleList=0D
+ //=0D
+ while (!IsListEmpty (&MapInfo->HandleList)) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (MapInfo->HandleList.Forwa=
rdLink);=0D
+ RemoveEntryList (&MapHandleInfo->Link);=0D
+ FreePool (MapHandleInfo);=0D
+ }=0D
+=0D
+ if (MapInfo->DeviceAddress !=3D MapInfo->HostAddress) {=0D
+ //=0D
+ // If this is a write operation from the Bus Master's point of view,=0D
+ // then copy the contents of the mapped buffer into the real buffer=0D
+ // so the processor can read the contents of the real buffer.=0D
+ //=0D
+ if (MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite ||=0D
+ MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ //=0D
+ // Free the mapped buffer and the MAP_INFO structure.=0D
+ //=0D
+ gBS->FreePages (MapInfo->DeviceAddress, MapInfo->NumberOfPages);=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_UNMAP, MapInfo->NumberOfBytes, MapInfo-=
+ FreePool (Mapping);=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: =3D=3D> 0x%08x\n", Pages));=
=0D
+=0D
+ //=0D
+ // Validate Attributes=0D
+ //=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) !=
=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ //=0D
+ // Check for invalid inputs=0D
+ //=0D
+ if (HostAddress =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ //=0D
+ // The only valid memory types are EfiBootServicesData and=0D
+ // EfiRuntimeServicesData=0D
+ //=0D
+ if (MemoryType !=3D EfiBootServicesData &&=0D
+ MemoryType !=3D EfiRuntimeServicesData) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ PhysicalAddress =3D DMA_MEMORY_TOP;=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) =3D=3D 0) {=
=0D
+ //=0D
+ // Limit allocations to memory below 4GB=0D
+ //=0D
+ PhysicalAddress =3D MIN (PhysicalAddress, SIZE_4GB - 1);=0D
+ }=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ MemoryType,=0D
+ Pages,=0D
+ &PhysicalAddress=0D
+ );=0D
+ if (!EFI_ERROR (Status)) {=0D
+ *HostAddress =3D (VOID *) (UINTN) PhysicalAddress;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_ALLOC_BUFFER, (UINT64) Pages, (UINT64=
) (*HostAddress));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: 0x%08x <=3D=3D\n", *HostAdd=
ress));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuFreeBuffer: 0x%\n", Pages));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_FREE_BUFFER, Pages, (UINT64) HostAddres=
s);=0D
+=0D
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages=
);=0D
+}=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ LIST_ENTRY *Link;=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ *NumberOfPages =3D MapInfo->NumberOfPages;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.c
new file mode 100644
index 000000000..82fbd1bc9
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.c
@@ -0,0 +1,703 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+UINT64 mBelow4GMemoryLimit;=0D
+UINT64 mAbove4GMemoryLimit;=0D
+=0D
+EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+VTD_ACCESS_REQUEST *mAccessRequest =3D NULL;=0D
+UINTN mAccessRequestCount =3D 0;=0D
+UINTN mAccessRequestMaxCount =3D 0;=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_ACCESS_REQUEST *NewAccessRequest;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // Optimization for memory.=0D
+ //=0D
+ // If the last record is to IoMmuAccess=3D0,=0D
+ // Check previous records and remove the matched entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ if ((mAccessRequest[Index].Segment =3D=3D Segment) &&=0D
+ (mAccessRequest[Index].SourceId.Uint16 =3D=3D SourceId.Uint16) &=
&=0D
+ (mAccessRequest[Index].BaseAddress =3D=3D BaseAddress) &&=0D
+ (mAccessRequest[Index].Length =3D=3D Length) &&=0D
+ (mAccessRequest[Index].IoMmuAccess !=3D 0)) {=0D
+ //=0D
+ // Remove this record [Index].=0D
+ // No need to add the new record.=0D
+ //=0D
+ if (Index !=3D mAccessRequestCount - 1) {=0D
+ CopyMem (=0D
+ &mAccessRequest[Index],=0D
+ &mAccessRequest[Index + 1],=0D
+ sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index=
)=0D
+ );=0D
+ }=0D
+ ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCE=
SS_REQUEST));=0D
+ mAccessRequestCount--;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequestCount >=3D mAccessRequestMaxCount) {=0D
+ NewAccessRequest =3D AllocateZeroPool (sizeof(*NewAccessRequest) * (mA=
ccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));=0D
+ if (NewAccessRequest =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mAccessRequestMaxCount +=3D MAX_VTD_ACCESS_REQUEST;=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest)=
* mAccessRequestCount);=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NewAccessRequest;=0D
+ }=0D
+=0D
+ ASSERT (mAccessRequestCount < mAccessRequestMaxCount);=0D
+=0D
+ mAccessRequest[mAccessRequestCount].Segment =3D Segment;=0D
+ mAccessRequest[mAccessRequestCount].SourceId =3D SourceId;=0D
+ mAccessRequest[mAccessRequestCount].BaseAddress =3D BaseAddress;=0D
+ mAccessRequest[mAccessRequestCount].Length =3D Length;=0D
+ mAccessRequest[mAccessRequestCount].IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ mAccessRequestCount++;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process Access Requests from before DMAR table is installed.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessRequestedAccessAttribute (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));=0D
+=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "PCI(S%x.B%x.D%x.F%x) ",=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId.Bits.Bus,=0D
+ mAccessRequest[Index].SourceId.Bits.Device,=0D
+ mAccessRequest[Index].SourceId.Bits.Function=0D
+ ));=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "(0x%lx~0x%lx) - %lx\n",=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ ));=0D
+ Status =3D SetAccessAttribute (=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId,=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NULL;=0D
+ mAccessRequestCount =3D 0;=0D
+ mAccessRequestMaxCount =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));=0D
+}=0D
+=0D
+/**=0D
+ Return UEFI memory map information.=0D
+=0D
+ @param[out] Below4GMemoryLimit The below 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+ @param[out] Above4GMemoryLimit The above 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+=0D
+**/=0D
+VOID=0D
+ReturnUefiMemoryMap (=0D
+ OUT UINT64 *Below4GMemoryLimit,=0D
+ OUT UINT64 *Above4GMemoryLimit=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR *NextEfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR TempEfiEntry;=0D
+ UINTN EfiMemoryMapSize;=0D
+ UINTN EfiMapKey;=0D
+ UINTN EfiDescriptorSize;=0D
+ UINT32 EfiDescriptorVersion;=0D
+ UINT64 MemoryBlockLength;=0D
+=0D
+ *Below4GMemoryLimit =3D 0;=0D
+ *Above4GMemoryLimit =3D 0;=0D
+=0D
+ //=0D
+ // Get the EFI memory map.=0D
+ //=0D
+ EfiMemoryMapSize =3D 0;=0D
+ EfiMemoryMap =3D NULL;=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+=0D
+ do {=0D
+ //=0D
+ // Use size returned back plus 1 descriptor for the AllocatePool.=0D
+ // We don't just multiply by 2 since the "for" loop below terminates o=
n=0D
+ // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize=
=0D
+ // we process bogus entries and create bogus E820 entries.=0D
+ //=0D
+ EfiMemoryMap =3D (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapS=
ize);=0D
+ if (EfiMemoryMap =3D=3D NULL) {=0D
+ ASSERT (EfiMemoryMap !=3D NULL);=0D
+ return;=0D
+ }=0D
+=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (EfiMemoryMap);=0D
+ }=0D
+ } while (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Sort memory map from low to high=0D
+ //=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ while (NextEfiEntry < EfiMemoryMapEnd) {=0D
+ if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {=0D
+ CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTO=
R));=0D
+ }=0D
+=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptor=
Size);=0D
+ }=0D
+=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "MemoryMap:\n"));=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ MemoryBlockLength =3D (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12=
));=0D
+ DEBUG ((DEBUG_INFO, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry->T=
ype, EfiEntry->PhysicalStart, EfiEntry->PhysicalStart + MemoryBlockLength))=
;=0D
+ switch (EfiEntry->Type) {=0D
+ case EfiLoaderCode:=0D
+ case EfiLoaderData:=0D
+ case EfiBootServicesCode:=0D
+ case EfiBootServicesData:=0D
+ case EfiConventionalMemory:=0D
+ case EfiRuntimeServicesCode:=0D
+ case EfiRuntimeServicesData:=0D
+ case EfiACPIReclaimMemory:=0D
+ case EfiACPIMemoryNVS:=0D
+ case EfiReservedMemoryType:=0D
+ if ((EfiEntry->PhysicalStart + MemoryBlockLength) <=3D BASE_1MB) {=0D
+ //=0D
+ // Skip the memory block is under 1MB=0D
+ //=0D
+ } else if (EfiEntry->PhysicalStart >=3D BASE_4GB) {=0D
+ if (*Above4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Above4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ } else {=0D
+ if (*Below4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Below4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ }=0D
+ break;=0D
+ }=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);=0D
+ }=0D
+=0D
+ FreePool (EfiMemoryMap);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Result:\n"));=0D
+ DEBUG ((DEBUG_INFO, "Below4GMemoryLimit: 0x%016lx\n", *Below4GMemoryLim=
it));=0D
+ DEBUG ((DEBUG_INFO, "Above4GMemoryLimit: 0x%016lx\n", *Above4GMemoryLim=
it));=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackAlwaysEnablePageAttribute (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ EFI_STATUS Status;=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (Segment, SourceId);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device in the DeviceScope.=
=0D
+=0D
+ @param[in] DeviceScope the input device scope data structure=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device scope.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeDeviceScope (=0D
+ IN EDKII_PLATFORM_VTD_DEVICE_SCOPE *DeviceScope=0D
+ )=0D
+{=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceS=
cope->DeviceScope, &Bus, &Device, &Function);=0D
+=0D
+ if (DeviceScope->DeviceScope.Type =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYP=
E_PCI_BRIDGE) {=0D
+ //=0D
+ // Need scan the bridge and add all devices.=0D
+ //=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Device=
Scope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIS=
TER_OFFSET));=0D
+ Status =3D ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusN=
umber, ScanBusCallbackAlwaysEnablePageAttribute);=0D
+ return Status;=0D
+ } else {=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, Sour=
ceId);=0D
+ return Status;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device matching DeviceId.=0D
+=0D
+ @param[in] PciDeviceId the input PCI device ID=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device matching DeviceId.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributePciDeviceId (=0D
+ IN EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ UINTN PciIndex;=0D
+ PCI_DEVICE_DATA *PciDeviceData;=0D
+ EFI_STATUS Status;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ for (PciIndex =3D 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDevic=
eInfo->PciDeviceDataNumber; PciIndex++) {=0D
+ PciDeviceData =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciD=
eviceData[PciIndex];=0D
+=0D
+ if (((PciDeviceId->VendorId =3D=3D 0xFFFF) || (PciDeviceId->VendorId=
=3D=3D PciDeviceData->PciDeviceId.VendorId)) &&=0D
+ ((PciDeviceId->DeviceId =3D=3D 0xFFFF) || (PciDeviceId->DeviceId=
=3D=3D PciDeviceData->PciDeviceId.DeviceId)) &&=0D
+ ((PciDeviceId->RevisionId =3D=3D 0xFF) || (PciDeviceId->Revision=
Id =3D=3D PciDeviceData->PciDeviceId.RevisionId)) &&=0D
+ ((PciDeviceId->SubsystemVendorId =3D=3D 0xFFFF) || (PciDeviceId-=
+ ((PciDeviceId->SubsystemDeviceId =3D=3D 0xFFFF) || (PciDeviceId-=
+ Status =3D AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex=
].Segment, PciDeviceData->PciSourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ continue;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] DeviceInfo the exception device information=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device info.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeExceptionDeviceInfo (=0D
+ IN EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *DeviceInfo=0D
+ )=0D
+{=0D
+ switch (DeviceInfo->Type) {=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:=0D
+ return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1))=
;=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:=0D
+ return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1))=
;=0D
+ default:=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN DeviceInfoCount;=0D
+ VOID *DeviceInfo;=0D
+ EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // It is optional.=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEdkiiPlatformVTdPolicyProtocolGuid,=0D
+ NULL,=0D
+ (VOID **)&mPlatformVTdPolicy=0D
+ );=0D
+ if (!EFI_ERROR(Status)) {=0D
+ DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));=0D
+ Status =3D mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPol=
icy, &DeviceInfoCount, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ ThisDeviceInfo =3D DeviceInfo;=0D
+ for (Index =3D 0; Index < DeviceInfoCount; Index++) {=0D
+ if (ThisDeviceInfo->Type =3D=3D EDKII_PLATFORM_VTD_EXCEPTION_DEVIC=
E_INFO_TYPE_END) {=0D
+ break;=0D
+ }=0D
+ AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);=0D
+ ThisDeviceInfo =3D (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo=
->Length);=0D
+ }=0D
+ FreePool (DeviceInfo);=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd engine.=0D
+**/=0D
+VOID=0D
+SetupVtd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VOID *PciEnumerationComplete;=0D
+ UINTN Index;=0D
+ UINT64 Below4GMemoryLimit;=0D
+ UINT64 Above4GMemoryLimit;=0D
+ VTD_ROOT_TABLE_INFO RootTableInfo;=0D
+=0D
+ //=0D
+ // PCI Enumeration must be done=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEfiPciEnumerationCompleteProtocolGuid,=0D
+ NULL,=0D
+ &PciEnumerationComplete=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ ReturnUefiMemoryMap (&Below4GMemoryLimit, &Above4GMemoryLimit);=0D
+ Below4GMemoryLimit =3D ALIGN_VALUE_UP(Below4GMemoryLimit, SIZE_256MB);=0D
+ DEBUG ((DEBUG_INFO, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GM=
emoryLimit));=0D
+=0D
+ mBelow4GMemoryLimit =3D Below4GMemoryLimit;=0D
+ mAbove4GMemoryLimit =3D Above4GMemoryLimit;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_SETUP_VTD, Below4GMemoryLimit, Above4GMemoryL=
imit);=0D
+=0D
+ //=0D
+ // 1. setup=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "ParseDmarAcpiTable\n"));=0D
+ Status =3D ParseDmarAcpiTableDrhd ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));=0D
+ PrepareVtdConfig ();=0D
+=0D
+ //=0D
+ // 2. initialization=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));=0D
+ Status =3D SetupTranslationTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ InitializePlatformVTdPolicy ();=0D
+=0D
+ ParseDmarAcpiTableRmrr ();=0D
+=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) =3D=3D 0) {=0D
+ //=0D
+ // Support IOMMU access attribute request recording before DMAR table =
is installed.=0D
+ // Here is to process the requests.=0D
+ //=0D
+ ProcessRequestedAccessAttribute ();=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInf=
ormation[Index].Segment));=0D
+=0D
+ if (mVtdUnitInformation[Index].ExtRootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
Index].ExtRootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 1, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[Index].RootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Ind=
ex].RootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 0, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // 3. enable=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar\n"));=0D
+ Status =3D EnableDmar ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "DumpVtdRegs\n"));=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Notification function of ACPI Table change.=0D
+=0D
+ This is a notification function registered on ACPI Table change event.=0D
+=0D
+ @param Event Event whose notification function is being invoked.=
=0D
+ @param Context Pointer to the notification function's context.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+AcpiNotificationFunc (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetDmarAcpiTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ if (Status =3D=3D EFI_ALREADY_STARTED) {=0D
+ gBS->CloseEvent (Event);=0D
+ }=0D
+ return;=0D
+ }=0D
+ SetupVtd ();=0D
+ gBS->CloseEvent (Event);=0D
+}=0D
+=0D
+/**=0D
+ Exit boot service callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnExitBootServices (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnExitBootServices\n"));=0D
+=0D
+ DumpVtdRegsAll ();=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidate all\n"));=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss);=0D
+=0D
+ InvalidateContextCache (VtdIndex);=0D
+=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) {=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Legacy boot callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnLegacyBoot (=0D
+ EFI_EVENT Event,=0D
+ VOID *Context=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnLegacyBoot\n"));=0D
+ DumpVtdRegsAll ();=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_EVENT ExitBootServicesEvent;=0D
+ EFI_EVENT LegacyBootEvent;=0D
+ EFI_EVENT EventAcpi10;=0D
+ EFI_EVENT EventAcpi20;=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi10TableGuid,=0D
+ &EventAcpi10=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi20TableGuid,=0D
+ &EventAcpi20=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Signal the events initially for the case=0D
+ // that DMAR table has been installed.=0D
+ //=0D
+ gBS->SignalEvent (EventAcpi20);=0D
+ gBS->SignalEvent (EventAcpi10);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ TPL_CALLBACK,=0D
+ OnExitBootServices,=0D
+ NULL,=0D
+ &gEfiEventExitBootServicesGuid,=0D
+ &ExitBootServicesEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D EfiCreateEventLegacyBootEx (=0D
+ TPL_CALLBACK,=0D
+ OnLegacyBoot,=0D
+ NULL,=0D
+ &LegacyBootEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ return ;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.h
new file mode 100644
index 000000000..5cd59d18e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.h
@@ -0,0 +1,658 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef _DMAR_PROTECTION_H_=0D
+#define _DMAR_PROTECTION_H_=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiDxe.h>=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/PciSegmentLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/UefiLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/PerformanceLib.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/ReportStatusCodeLib.h>=0D
+#include <Library/HobLib.h>=0D
+=0D
+#include <Guid/EventGroup.h>=0D
+#include <Guid/Acpi.h>=0D
+=0D
+#include <Protocol/VtdLog.h>=0D
+#include <Protocol/DxeSmmReadyToLock.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+#include <Protocol/PciIo.h>=0D
+#include <Protocol/PciEnumerationComplete.h>=0D
+#include <Protocol/PlatformVtdPolicy.h>=0D
+#include <Protocol/IoMmu.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+=0D
+#include <IndustryStandard/Pci.h>=0D
+#include <IndustryStandard/DmaRemappingReportingTable.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (=
~((Alignment) - 1)))=0D
+#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))=
=0D
+=0D
+#define VTD_TPL_LEVEL TPL_NOTIFY=0D
+=0D
+//=0D
+// Use 256-bit descriptor=0D
+// Queue size is 128.=0D
+//=0D
+#define VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH 1=0D
+#define VTD_INVALIDATION_QUEUE_SIZE 0=0D
+=0D
+//=0D
+// This is the initial max PCI DATA number.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_PCI_DATA_NUMBER 0x100=0D
+=0D
+typedef struct {=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Segment;=0D
+ VTD_VER_REG VerReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_ROOT_ENTRY *RootEntryTable;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntryTable;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *FixedSecondLevelPagingEntry;=0D
+ BOOLEAN HasDirtyContext;=0D
+ BOOLEAN HasDirtyPages;=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ BOOLEAN Is5LevelPaging;=0D
+ UINT8 EnableQueuedInvalidation;=0D
+ VOID *QiDescBuffer;=0D
+ UINTN QiDescBufferSize;=0D
+} VTD_UNIT_INFORMATION;=0D
+=0D
+//=0D
+// This is the initial max ACCESS request.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_ACCESS_REQUEST 0x100=0D
+=0D
+typedef struct {=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 Length;=0D
+ UINT64 IoMmuAccess;=0D
+} VTD_ACCESS_REQUEST;=0D
+=0D
+=0D
+/**=0D
+ The scan bus callback function.=0D
+=0D
+ It is called in PCI bus scan for each PCI device under the bus.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The specific PCI device is processed in th=
e callback.=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *SCAN_BUS_FUNC_CALLBACK_FUNC) (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+extern EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;=0D
+=0D
+extern UINTN mVtdUnitNumber;=0D
+extern VTD_UNIT_INFORMATION *mVtdUnitInformation;=0D
+=0D
+extern UINT64 mBelow4GMemoryLimit;=0D
+extern UINT64 mAbove4GMemoryLimit;=0D
+=0D
+extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegs (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers for all VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegsAll (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd extended capability registers.=0D
+=0D
+ @param[in] ECapReg The extended capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdECapRegs (=0D
+ IN VTD_ECAP_REG *ECapReg=0D
+ );=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ );=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ );=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR RMRR table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR RMRR table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ );=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ );=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ );=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ );=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dmar=
AcpiTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
rAcpiTable.c
new file mode 100644
index 000000000..21f559983
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmarAcpiTab=
le.c
@@ -0,0 +1,398 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#pragma pack(1)=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT32 Entry;=0D
+} RSDT_TABLE;=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT64 Entry;=0D
+} XSDT_TABLE;=0D
+=0D
+#pragma pack()=0D
+=0D
+EFI_ACPI_DMAR_HEADER *mAcpiDmarTable =3D NULL;=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+**/=0D
+VOID=0D
+VtdDumpDmarTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VtdLibDumpAcpiDmar (NULL, NULL, (EFI_ACPI_DMAR_HEADER *) (UINTN) mAcpiDm=
arTable);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_DMAR_TABLE, mAcpiDmarTable->Header.Length=
, (VOID *)mAcpiDmarTable, mAcpiDmarTable->Header.Length); =0D
+}=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;=0D
+ UINT8 MyBus;=0D
+ UINT8 MyDevice;=0D
+ UINT8 MyFunction;=0D
+=0D
+ DmarPciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)((UINTN)(DmarDevScopeEntry + 1=
));=0D
+ MyBus =3D DmarDevScopeEntry->StartBusNumber;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ while ((UINTN)DmarPciPath + sizeof(EFI_ACPI_DMAR_PCI_PATH) < (UINTN)Dm=
arDevScopeEntry + DmarDevScopeEntry->Length) {=0D
+ MyBus =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, MyBus, M=
yDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=0D
+ DmarPciPath ++;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+ }=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ break;=0D
+ }=0D
+=0D
+ *Bus =3D MyBus;=0D
+ *Device =3D MyDevice;=0D
+ *Function =3D MyFunction;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR DRHD table.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] DmarDrhd The DRHD table.=0D
+=0D
+ @retval EFI_SUCCESS The DRHD table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessDrhd (=0D
+ IN UINTN VtdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D AllocateZeroPool (sizeof=
(PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVICE_DATA) * MAX_VTD_PCI_DATA_NUM=
BER);=0D
+ if (mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D=3D NULL) {=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Segment =3D DmarDrhd->SegmentNu=
mber;=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress =3D (UINTN)DmarDrhd->Re=
gisterBaseAddress;=0D
+ DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, Dma=
rDrhd->RegisterBaseAddress));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->Segment =3D =
DmarDrhd->SegmentNumber;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataMaxNumber =3D =
MAX_VTD_PCI_DATA_NUMBER;=0D
+=0D
+ if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) !=3D 0)=
{=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D TRUE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n"));=0D
+=0D
+ Status =3D ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Sc=
anBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ } else {=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D FALSE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n"));=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarDrhd + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Len=
gth) {=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: "));=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ DEBUG ((DEBUG_INFO,"PCI Endpoint"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ DEBUG ((DEBUG_INFO,"IOAPIC"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ DEBUG ((DEBUG_INFO,"MSI Capable HPET"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));=0D
+ break;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumb=
er, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, DmarDrhd->SegmentNumber, Sourc=
eId, DmarDevScopeEntry->Type, TRUE);=0D
+ if (EFI_ERROR (Status)) {=0D
+ //=0D
+ // There might be duplication for special device other than standard=
PCI device.=0D
+ //=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Dmar=
Drhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIST=
ER_OFFSET));=0D
+ Status =3D ScanPciBus ((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Se=
condaryBusNumber, ScanBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR RMRR table.=0D
+=0D
+ @param[in] DmarRmrr The RMRR table.=0D
+=0D
+ @retval EFI_SUCCESS The RMRR table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessRmrr (=0D
+ IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr-=
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarRmrr + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Len=
gth) {=0D
+ if (DmarDevScopeEntry->Type !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_=
ENDPOINT) {=0D
+ DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%=
x] \n", DmarDevScopeEntry->Type));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->Segment=
Number, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D SetAccessAttribute (=0D
+ DmarRmrr->SegmentNumber,=0D
+ SourceId,=0D
+ DmarRmrr->ReservedMemoryRegionBaseAddress,=0D
+ DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->=
ReservedMemoryRegionBaseAddress,=0D
+ EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Get VTd engine number.=0D
+**/=0D
+UINTN=0D
+GetVtdEngineNumber (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ UINTN VtdIndex;=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdIndex++;=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return VtdIndex ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+ UINTN VtdIndex;=0D
+=0D
+ mVtdUnitNumber =3D GetVtdEngineNumber ();=0D
+ DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));=0D
+ ASSERT (mVtdUnitNumber > 0);=0D
+ if (mVtdUnitNumber =3D=3D 0) {=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ mVtdUnitInformation =3D AllocateZeroPool (sizeof(*mVtdUnitInformation) *=
mVtdUnitNumber);=0D
+ ASSERT (mVtdUnitInformation !=3D NULL);=0D
+ if (mVtdUnitInformation =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ ASSERT (VtdIndex < mVtdUnitNumber);=0D
+ Status =3D ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarH=
eader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ VtdIndex++;=0D
+=0D
+ break;=0D
+=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ ASSERT (VtdIndex =3D=3D mVtdUnitNumber);=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibDumpPciDeviceInfo (NULL, NULL, mVtdUnitInformation[VtdIndex].Pci=
DeviceInfo);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_PCI_DEVICE,=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress,=
=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo,=0D
+ sizeof (PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVI=
CE_DATA) * mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataNumber=
);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_RMRR:=0D
+ Status =3D ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (mAcpiDmarTable !=3D NULL) {=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+=0D
+ mAcpiDmarTable =3D (EFI_ACPI_DMAR_HEADER *) EfiLocateFirstAcpiTable (=0D
+ EFI_ACPI_4_0_DMA_REMAPPING_T=
ABLE_SIGNATURE=0D
+ );=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ return EFI_NOT_FOUND;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));=0D
+ VtdDumpDmarTable();=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/I=
ntelVTdCoreDxe.c
new file mode 100644
index 000000000..6e8c87e1f
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.c
@@ -0,0 +1,787 @@
+/** @file=0D
+ Intel VTd driver.=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ );=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ );=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ )=0D
+{=0D
+ EFI_PCI_IO_PROTOCOL *PciIo;=0D
+ UINTN Seg;=0D
+ UINTN Bus;=0D
+ UINTN Dev;=0D
+ UINTN Func;=0D
+ EFI_STATUS Status;=0D
+ EDKII_PLATFORM_VTD_DEVICE_INFO DeviceInfo;=0D
+=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (mPlatformVTdPolicy !=3D NULL) {=0D
+ Status =3D mPlatformVTdPolicy->GetDeviceId (mPlatformVTdPolicy, Device=
Handle, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ *Segment =3D DeviceInfo.Segment;=0D
+ *SourceId =3D DeviceInfo.SourceId;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D gBS->HandleProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (V=
OID **)&PciIo);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ Status =3D PciIo->GetLocation (PciIo, &Seg, &Bus, &Dev, &Func);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ *Segment =3D (UINT16)Seg;=0D
+ SourceId->Bits.Bus =3D (UINT8)Bus;=0D
+ SourceId->Bits.Device =3D (UINT8)Dev;=0D
+ SourceId->Bits.Function =3D (UINT8)Func;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER DeviceAddress is not IoMmu Page size alig=
ned.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VTdSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ CHAR8 PerfToken[sizeof("VTD(S0000.B00.D00.F00)")];=
=0D
+ UINT32 Identifier;=0D
+ VTD_PROTOCOL_SET_ATTRIBUTE LogSetAttribute;=0D
+=0D
+ DumpVtdIfError ();=0D
+=0D
+ Status =3D DeviceHandleToSourceId (DeviceHandle, &Segment, &SourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuSetAttribute: "));=0D
+ DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment, SourceId.Bits.B=
us, SourceId.Bits.Device, SourceId.Bits.Function));=0D
+ DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length, I=
oMmuAccess));=0D
+=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ //=0D
+ // Record the entry to driver global variable.=0D
+ // As such once VTd is activated, the setting can be adopted.=0D
+ //=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) !=3D 0) {=0D
+ //=0D
+ // Force no IOMMU access attribute request recording before DMAR tab=
le is installed.=0D
+ //=0D
+ ASSERT_EFI_ERROR (EFI_NOT_READY);=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ Status =3D RequestAccessAttribute (Segment, SourceId, DeviceAddress, L=
ength, IoMmuAccess);=0D
+ } else {=0D
+ PERF_CODE (=0D
+ AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", S=
egment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_START_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=
=0D
+ );=0D
+=0D
+ Status =3D SetAccessAttribute (Segment, SourceId, DeviceAddress, Lengt=
h, IoMmuAccess);=0D
+=0D
+ PERF_CODE (=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_END_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=0D
+ );=0D
+ }=0D
+=0D
+ if (!EFI_ERROR(Status)) {=0D
+ SyncDeviceHandleToMapInfo (=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ LogSetAttribute.SourceId.Uint16 =3D SourceId.Uint16;=0D
+ LogSetAttribute.DeviceAddress =3D DeviceAddress;=0D
+ LogSetAttribute.Length =3D Length;=0D
+ LogSetAttribute.IoMmuAccess =3D IoMmuAccess;=0D
+ LogSetAttribute.Status =3D Status;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_IOMMU_SET_ATTRIBUTE, 0, &LogSetAttribute,=
sizeof (VTD_PROTOCOL_SET_ATTRIBUTE));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] Mapping The mapping value returned from Map().=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned =
by Map().=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by Mapping.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN VOID *Mapping,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ UINTN NumberOfPages;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+=0D
+ Status =3D GetDeviceInfoFromMapping (Mapping, &DeviceAddress, &NumberOfP=
ages);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ Status =3D VTdSetAttribute (=0D
+ This,=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ EFI_PAGES_TO_SIZE(NumberOfPages),=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+EDKII_IOMMU_PROTOCOL mIntelVTd =3D {=0D
+ EDKII_IOMMU_PROTOCOL_REVISION,=0D
+ IoMmuSetAttribute,=0D
+ IoMmuMap,=0D
+ IoMmuUnmap,=0D
+ IoMmuAllocateBuffer,=0D
+ IoMmuFreeBuffer,=0D
+};=0D
+=0D
+UINT8 *mVtdLogBuffer =3D NULL;=0D
+=0D
+UINT8 *mVtdLogDxeFreeBuffer =3D NULL;=0D
+UINT32 mVtdLogDxeBufferUsed =3D 0;=0D
+=0D
+UINT32 mVtdLogPeiPostMemBufferUsed =3D 0;=0D
+=0D
+UINT8 mVtdLogPeiError =3D 0;=0D
+UINT16 mVtdLogDxeError =3D 0;=0D
+=0D
+/**=0D
+ Allocate memory buffer for VTd log items.=0D
+=0D
+ @param[in] MemorySize Required memory buffer size.=0D
+=0D
+ @retval Buffer address=0D
+=0D
+**/=0D
+UINT8 *=0D
+EFIAPI=0D
+VTdLogAllocMemory (=0D
+ IN CONST UINT32 MemorySize=0D
+ )=0D
+{=0D
+ UINT8 *Buffer;=0D
+=0D
+ Buffer =3D NULL;=0D
+ if (mVtdLogDxeFreeBuffer !=3D NULL) {=0D
+ if ((mVtdLogDxeBufferUsed + MemorySize) <=3D PcdGet32 (PcdVTdDxeLogBuf=
ferSize)) {=0D
+ Buffer =3D mVtdLogDxeFreeBuffer;=0D
+=0D
+ mVtdLogDxeFreeBuffer +=3D MemorySize;=0D
+ mVtdLogDxeBufferUsed +=3D MemorySize;=0D
+ } else {=0D
+ mVtdLogDxeError |=3D VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ }=0D
+ return Buffer;=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM *Item;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ Item =3D (VTDLOG_EVENT_2PARAM *) VTdLogAllocMemory (sizeof (VTDLOG_EVENT=
_2PARAM));=0D
+ if (Item !=3D NULL) {=0D
+ Item->Data1 =3D Data1;=0D
+ Item->Data2 =3D Data2;=0D
+=0D
+ Item->Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_CONTEXT *Item;=0D
+ UINT32 EventSize;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ EventSize =3D sizeof (VTDLOG_EVENT_CONTEXT) + DataSize - 1;=0D
+=0D
+ Item =3D (VTDLOG_EVENT_CONTEXT *) VTdLogAllocMemory (EventSize);=0D
+ if (Item !=3D NULL) {=0D
+ Item->Param =3D Param;=0D
+ CopyMem (Item->Data, Data, DataSize);=0D
+=0D
+ Item->Header.DataSize =3D EventSize;=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+ =0D
+/**=0D
+ Get Event Items From Pei Pre-Mem Buffer=0D
+=0D
+ @param[in] Buffer Pre-Memory data buffer.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log event=
=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromPeiPreMemBuffer (=0D
+ IN VTDLOG_PEI_PRE_MEM_INFO *InfoBuffer,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINT64 EventCount;=0D
+ VTDLOG_EVENT_2PARAM Event;=0D
+=0D
+ if (InfoBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ EventCount =3D 0;=0D
+ for (Index =3D 0; Index < VTD_LOG_PEI_PRE_MEM_BAR_MAX; Index++) {=0D
+ if (InfoBuffer[Index].Mode =3D=3D VTD_LOG_PEI_PRE_MEM_NOT_USED) {=0D
+ continue;=0D
+ }=0D
+ if (CallbackHandle) {=0D
+ Event.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Event.Header.Timestamp =3D 0;=0D
+=0D
+ Event.Header.LogType =3D ((UINT64) 1) << VTDLOG_PEI_PRE_MEM_DMA_PROT=
ECT;=0D
+ Event.Data1 =3D InfoBuffer[Index].BarAddress;=0D
+ Event.Data2 =3D InfoBuffer[Index].Mode;=0D
+ Event.Data2 |=3D InfoBuffer[Index].Status<<8;=0D
+ CallbackHandle (Context, &Event.Header);=0D
+ }=0D
+ EventCount++;=0D
+ }=0D
+=0D
+ return EventCount;=0D
+}=0D
+=0D
+/**=0D
+ Get Event Items From Pei Post-Mem/Dxe Buffer=0D
+=0D
+ @param[in] Buffer Data buffer.=0D
+ @param[in] BufferUsed Data buffer used.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromBuffer (=0D
+ IN UINT8 *Buffer,=0D
+ IN UINT32 BufferUsed,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 Count;=0D
+ VTDLOG_EVENT_HEADER *Header;=0D
+=0D
+ Count =3D 0;=0D
+ if (Buffer !=3D NULL) {=0D
+ while (BufferUsed > 0) {=0D
+ Header =3D (VTDLOG_EVENT_HEADER *) Buffer;=0D
+ if (BufferUsed >=3D Header->DataSize) {=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, Header);=0D
+ }=0D
+ Buffer +=3D Header->DataSize;=0D
+ BufferUsed -=3D Header->DataSize;=0D
+ Count++;=0D
+ } else {=0D
+ BufferUsed =3D 0;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return Count;=0D
+}=0D
+=0D
+/**=0D
+ Generate the VTd log state.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdGenerateStateEvent (=0D
+ IN VTDLOG_EVENT_TYPE EventType,=0D
+ IN UINT64 Data1,=0D
+ IN UINT64 Data2,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM Item;=0D
+=0D
+ Item.Data1 =3D Data1;=0D
+ Item.Data2 =3D Data2;=0D
+=0D
+ Item.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item.Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item.Header.Timestamp =3D 0;=0D
+=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, &Item.Header);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Get the VTd log events.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdLogGetEvents (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 CountPeiPreMem;=0D
+ UINT64 CountPeiPostMem;=0D
+ UINT64 CountDxe;=0D
+ UINT8 *Buffer;=0D
+=0D
+ if (mVtdLogBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ //=0D
+ // PEI pre-memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (=
PcdVTdPeiPostMemLogBufferSize)];=0D
+ CountPeiPreMem =3D VTdGetEventItemsFromPeiPreMemBuffer ((VTDLOG_PEI_PRE_=
MEM_INFO *) Buffer, Context, CallbackHandle);=0D
+ DEBUG ((DEBUG_INFO, "Find %d in PEI pre mem phase\n", CountPeiPreMem));=
=0D
+=0D
+ //=0D
+ // PEI post memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize)];=0D
+ CountPeiPostMem =3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogPeiPostMe=
mBufferUsed, Context, CallbackHandle);=0D
+ if (mVtdLogPeiError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_PEI_BASIC, mVtdLogPeiError, 0, Context, =
CallbackHandle);=0D
+ CountPeiPostMem++;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "Find %d in PEI post mem phase\n", CountPeiPostMem))=
;=0D
+=0D
+ //=0D
+ // DXE phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[0];=0D
+ CountDxe =3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogDxeBufferUsed, C=
ontext, CallbackHandle);=0D
+ if (mVtdLogDxeError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_DXE_BASIC, mVtdLogDxeError, 0, Context, =
CallbackHandle);=0D
+ CountDxe++;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "Find %d in DXE phase\n", CountDxe));=0D
+=0D
+ return CountPeiPreMem + CountPeiPostMem + CountDxe;=0D
+}=0D
+=0D
+EDKII_VTD_LOG_PROTOCOL mIntelVTdLog =3D {=0D
+ EDKII_VTD_LOG_PROTOCOL_REVISION,=0D
+ VTdLogGetEvents=0D
+};=0D
+=0D
+/**=0D
+ Initializes the VTd Log.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogInitialize(=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINT32 TotalBufferSize;=0D
+ EFI_STATUS Status;=0D
+ VOID *HobPtr;=0D
+ VTDLOG_PEI_BUFFER_HOB *HobPeiBuffer;=0D
+ EFI_HANDLE Handle;=0D
+ UINT32 BufferOffset;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ }=0D
+=0D
+ if (mVtdLogBuffer !=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ TotalBufferSize =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTd=
PeiPostMemLogBufferSize) + sizeof (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_P=
RE_MEM_BAR_MAX;=0D
+=0D
+ Status =3D gBS->AllocatePool (EfiBootServicesData, TotalBufferSize, &mVt=
dLogBuffer);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // DXE Buffer=0D
+ //=0D
+ if (PcdGet32 (PcdVTdDxeLogBufferSize) > 0) {=0D
+ mVtdLogDxeFreeBuffer =3D mVtdLogBuffer;=0D
+ mVtdLogDxeBufferUsed =3D 0;=0D
+ }=0D
+=0D
+ //=0D
+ // Get PEI pre-memory buffer offset=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTdPei=
PostMemLogBufferSize);=0D
+=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ HobPeiBuffer =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ //=0D
+ // Copy PEI pre-memory phase VTd log.=0D
+ //=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], &HobPeiBuffer->PreMemInfo, size=
of (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+=0D
+ //=0D
+ // Copy PEI post-memory pase VTd log.=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize);=0D
+ if (PcdGet32 (PcdVTdPeiPostMemLogBufferSize) > 0) {=0D
+ if (HobPeiBuffer->PostMemBufferUsed > 0) {=0D
+ mVtdLogPeiPostMemBufferUsed =3D HobPeiBuffer->PostMemBufferUsed;=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], (UINT8 *) (UINTN) HobPeiBuf=
fer->PostMemBuffer, mVtdLogPeiPostMemBufferUsed);=0D
+ }=0D
+ }=0D
+=0D
+ mVtdLogPeiError =3D HobPeiBuffer->VtdLogPeiError;=0D
+ } else {=0D
+ //=0D
+ // Do not find PEI Vtd log, clear PEI pre-memory phase buffer.=0D
+ //=0D
+ ZeroMem (&mVtdLogBuffer[BufferOffset], sizeof (VTDLOG_PEI_PRE_MEM_INFO=
) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+ }=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiVTdLogProtocolGuid,=0D
+ &mIntelVTdLog,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+}=0D
+=0D
+/**=0D
+ Initialize the VTd driver.=0D
+=0D
+ @param[in] ImageHandle ImageHandle of the loaded driver=0D
+ @param[in] SystemTable Pointer to the System Table=0D
+=0D
+ @retval EFI_SUCCESS The Protocol is installed.=0D
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial=
ize driver.=0D
+ @retval EFI_DEVICE_ERROR A device error occurred attempting to ini=
tialize the driver.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IntelVTdInitialize (=0D
+ IN EFI_HANDLE ImageHandle,=0D
+ IN EFI_SYSTEM_TABLE *SystemTable=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_HANDLE Handle;=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VTdLogInitialize ();=0D
+=0D
+ InitializeDmaProtection ();=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiIoMmuProtocolGuid, &mIntelVTd,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL, Status, 0);=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.inf
new file mode 100644
index 000000000..6f3c9e7df
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.inf
@@ -0,0 +1,92 @@
+## @file=0D
+# Intel VTd DXE Driver.=0D
+#=0D
+# This driver initializes VTd engine based upon DMAR ACPI tables=0D
+# and provide DMA protection to PCI or ACPI device.=0D
+#=0D
+# Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdCoreDxe=0D
+ MODULE_UNI_FILE =3D IntelVTdCoreDxe.uni=0D
+ FILE_GUID =3D 5c83381f-34d3-4672-b8f3-83c3d6f3b00e=
=0D
+ MODULE_TYPE =3D DXE_DRIVER=0D
+ VERSION_STRING =3D 1.0=0D
+ ENTRY_POINT =3D IntelVTdInitialize=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D IA32 X64 EBC=0D
+#=0D
+#=0D
+=0D
+[Sources]=0D
+ IntelVTdCoreDxe.c=0D
+ BmDma.c=0D
+ DmaProtection.c=0D
+ DmaProtection.h=0D
+ DmarAcpiTable.c=0D
+ PciInfo.c=0D
+ TranslationTable.c=0D
+ TranslationTableEx.c=0D
+ VtdReg.c=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ UefiDriverEntryPoint=0D
+ UefiBootServicesTableLib=0D
+ BaseLib=0D
+ IoLib=0D
+ HobLib=0D
+ PciSegmentLib=0D
+ BaseMemoryLib=0D
+ MemoryAllocationLib=0D
+ UefiLib=0D
+ CacheMaintenanceLib=0D
+ PerformanceLib=0D
+ PrintLib=0D
+ ReportStatusCodeLib=0D
+ IntelVTdPeiDxeLib=0D
+=0D
+[Guids]=0D
+ gVTdLogBufferHobGuid ## CONSUMES=0D
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi20TableGuid=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi10TableGuid=0D
+=0D
+[Protocols]=0D
+ gEdkiiIoMmuProtocolGuid ## PRODUCES=0D
+ gEfiPciIoProtocolGuid ## CONSUMES=0D
+ gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES=0D
+ gEdkiiPlatformVTdPolicyProtocolGuid ## SOMETIMES_CONSUMES=0D
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES=0D
+ gEdkiiVTdLogProtocolGuid ## PRODUCES=0D
+=0D
+[Pcd]=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdDxeLogBufferSize ## CONSUME=
S=0D
+=0D
+[Depex]=0D
+ gEfiPciRootBridgeIoProtocolGuid=0D
+=0D
+[UserExtensions.TianoCore."ExtraFiles"]=0D
+ IntelVTdCoreDxeExtra.uni=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.uni
new file mode 100644
index 000000000..73d2c83c4
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Module Localized Abstract and Description Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Intel VTd CORE DX=
E Driver."=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "This driver initi=
alizes VTd engine based upon DMAR ACPI tables and provide DMA protection to=
PCI or ACPI device."=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxeExtra.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCo=
reDxe/IntelVTdCoreDxeExtra.uni
new file mode 100644
index 000000000..7f1aec65e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxeExtra.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Localized Strings and Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+#string STR_PROPERTIES_MODULE_NAME=0D
+#language en-US=0D
+"Intel VTd CORE DXE Driver"=0D
+=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciI=
nfo.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
new file mode 100644
index 000000000..394ef734c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
@@ -0,0 +1,419 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ return (UINTN)-1;=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if ((PciSourceId->Bits.Bus =3D=3D SourceId.Bits.Bus) &&=0D
+ (PciSourceId->Bits.Device =3D=3D SourceId.Bits.Device) &&=0D
+ (PciSourceId->Bits.Function =3D=3D SourceId.Bits.Function) ) {=0D
+ return Index;=0D
+ }=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ )=0D
+{=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ UINTN PciDataIndex;=0D
+ UINTN Index;=0D
+ //PCI_DEVICE_DATA *NewPciDeviceData;=0D
+ PCI_DEVICE_INFORMATION *NewPciDeviceInfo;=0D
+ EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId;=0D
+=0D
+ PciDeviceInfo =3D mVtdUnitInformation[VtdIndex].PciDeviceInfo;=0D
+=0D
+ if (PciDeviceInfo->IncludeAllFlag) {=0D
+ //=0D
+ // Do not register device in other VTD Unit=0D
+ //=0D
+ for (Index =3D 0; Index < VtdIndex; Index++) {=0D
+ PciDataIndex =3D GetPciDataIndex (Index, Segment, SourceId);=0D
+ if (PciDataIndex !=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%=
02x already registered by Other Vtd(%d)\n", Segment, SourceId.Bits.Bus, Sou=
rceId.Bits.Device, SourceId.Bits.Function, Index));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ //=0D
+ // Register new=0D
+ //=0D
+=0D
+ if (PciDeviceInfo->PciDeviceDataNumber >=3D PciDeviceInfo->PciDeviceDa=
taMaxNumber) {=0D
+ //=0D
+ // Reallocate=0D
+ //=0D
+ NewPciDeviceInfo =3D AllocateZeroPool (sizeof (PCI_DEVICE_INFORMATIO=
N) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber + MA=
X_VTD_PCI_DATA_NUMBER));=0D
+ if (NewPciDeviceInfo =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ CopyMem (NewPciDeviceInfo, PciDeviceInfo, sizeof (PCI_DEVICE_INFORMA=
TION) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber +=
MAX_VTD_PCI_DATA_NUMBER));=0D
+ FreePool (PciDeviceInfo);=0D
+=0D
+ NewPciDeviceInfo->PciDeviceDataMaxNumber +=3D MAX_VTD_PCI_DATA_NUMBE=
R;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ }=0D
+=0D
+ ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceD=
ataMaxNumber);=0D
+=0D
+ PciSourceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciSourceId;=0D
+ PciSourceId->Bits.Bus =3D SourceId.Bits.Bus;=0D
+ PciSourceId->Bits.Device =3D SourceId.Bits.Device;=0D
+ PciSourceId->Bits.Function =3D SourceId.Bits.Function;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x"=
, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)=
);=0D
+=0D
+ PciDeviceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciDeviceId;=0D
+ if ((DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) =
||=0D
+ (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=
=0D
+ PciDeviceId->VendorId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->DeviceId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_DEVICE_ID_OFFSET));=0D
+ PciDeviceId->RevisionId =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS=
(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, =
PCI_REVISION_ID_OFFSET));=0D
+=0D
+ DEBUG ((DEBUG_INFO, " (%04x:%04x:%02x", PciDeviceId->VendorId, PciDe=
viceId->DeviceId, PciDeviceId->RevisionId));=0D
+=0D
+ if (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT)=
{=0D
+ PciDeviceId->SubsystemVendorId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->SubsystemDeviceId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_ID_OFFSET));=0D
+ DEBUG ((DEBUG_INFO, ":%04x:%04x", PciDeviceId->SubsystemVendorId, =
PciDeviceId->SubsystemDeviceId));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, ")"));=0D
+ }=0D
+=0D
+ PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDeviceDataNumber].Devic=
eType =3D DeviceType;=0D
+=0D
+ if ((DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) &&=
=0D
+ (DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=0D
+ DEBUG ((DEBUG_INFO, " (*)"));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "\n"));=0D
+=0D
+ PciDeviceInfo->PciDeviceDataNumber++;=0D
+ } else {=0D
+ if (CheckExist) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02=
x already registered\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, =
SourceId.Bits.Function));=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to register PCI device.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN VtdIndex;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT8 DeviceType;=0D
+ EFI_STATUS Status;=0D
+=0D
+ VtdIndex =3D (UINTN)Context;=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Dev=
ice, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, De=
vice, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, Segment, SourceId, DeviceType, F=
ALSE);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ UINT8 HeaderType;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT16 VendorID;=0D
+ UINT16 DeviceID;=0D
+ EFI_STATUS Status;=0D
+=0D
+ // Scan the PCI bus for devices=0D
+ for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) {=0D
+ for (Function =3D 0; Function <=3D PCI_MAX_FUNC; Function++) {=0D
+ VendorID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_VENDOR_ID_OFFSET));=0D
+ DeviceID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_DEVICE_ID_OFFSET));=0D
+ if (VendorID =3D=3D 0xFFFF && DeviceID =3D=3D 0xFFFF) {=0D
+ if (Function =3D=3D 0) {=0D
+ //=0D
+ // If function 0 is not implemented, do not scan other functions=
.=0D
+ //=0D
+ break;=0D
+ }=0D
+ continue;=0D
+ }=0D
+=0D
+ Status =3D Callback (Context, Segment, Bus, Device, Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus,=
Device, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(=
Segment, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=
=0D
+ DEBUG ((DEBUG_INFO," ScanPciBus: PCI bridge S%04x B%02x D%02x F=
%02x (SecondBus:%02x)\n", Segment, Bus, Device, Function, SecondaryBusNumbe=
r));=0D
+ if (SecondaryBusNumber !=3D 0) {=0D
+ Status =3D ScanPciBus (Context, Segment, SecondaryBusNumber, C=
allback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (Function =3D=3D 0) {=0D
+ HeaderType =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, B=
us, Device, 0, PCI_HEADER_TYPE_OFFSET));=0D
+ if ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) =3D=3D 0x00) {=0D
+ //=0D
+ // It is not a multi-function device, do not scan other function=
s.=0D
+ //=0D
+ break;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ UINTN HandleCount;=0D
+ EFI_HANDLE *HandleBuffer;=0D
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;=0D
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ScanAllPciBus ()\n"));=0D
+=0D
+ Status =3D gBS->LocateHandleBuffer (=0D
+ ByProtocol,=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ NULL,=0D
+ &HandleCount,=0D
+ &HandleBuffer=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Find %d root bridges\n", HandleCount));=0D
+=0D
+ for (Index =3D 0; Index < HandleCount; Index++) {=0D
+ Status =3D gBS->HandleProtocol (=0D
+ HandleBuffer[Index],=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ (VOID **) &PciRootBridgeIo=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) =
&Descriptors);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ while (Descriptors->Desc !=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ if (Descriptors->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_BUS) {=0D
+ break;=0D
+ }=0D
+ Descriptors++;=0D
+ }=0D
+=0D
+ if (Descriptors->Desc =3D=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ continue;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Scan root bridges : %d, Segment : %d, Bus : 0x%02X=
\n", Index, PciRootBridgeIo->SegmentNumber, Descriptors->AddrRangeMin));=0D
+ Status =3D ScanPciBus(Context, (UINT16) PciRootBridgeIo->SegmentNumber=
, (UINT8) Descriptors->AddrRangeMin, Callback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ FreePool(HandleBuffer);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ThisContextEntry;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ThisExtContextEntry;=0D
+ UINTN PciDataIndex;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ continue;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ continue;=0D
+ }=0D
+=0D
+// DEBUG ((DEBUG_INFO,"FindVtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n=
", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bit=
s.Function));=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D 0) {=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[So=
urceId.Index.RootIndex];=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_=
ADDRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.L=
owerContextTablePointerHi) ;=0D
+ ThisExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.Contex=
tIndex];=0D
+ if (ThisExtContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D ThisExtContextEntry;=0D
+ *ContextEntry =3D NULL;=0D
+ } else {=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId=
.Index.RootIndex];=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS=
(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointer=
Hi) ;=0D
+ ThisContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex=
];=0D
+ if (ThisContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D NULL;=0D
+ *ContextEntry =3D ThisContextEntry;=0D
+ }=0D
+=0D
+ return VtdIndex;=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/=
TranslationTable.c
new file mode 100644
index 000000000..37ca6e405
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
Table.c
@@ -0,0 +1,1112 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ )=0D
+{=0D
+ VOID *Addr;=0D
+=0D
+ Addr =3D AllocatePages (Pages);=0D
+ if (Addr =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ ZeroMem (Addr, EFI_PAGES_TO_SIZE(Pages));=0D
+ return Addr;=0D
+}=0D
+=0D
+/**=0D
+ Set second level paging entry attribute based upon IoMmuAccess.=0D
+=0D
+ @param[in] PtEntry The paging entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+**/=0D
+VOID=0D
+SetSecondLevelPagingEntryAttribute (=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PtEntry,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ PtEntry->Bits.Read =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_READ) !=3D 0)=
;=0D
+ PtEntry->Bits.Write =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_WRITE) !=3D 0=
);=0D
+}=0D
+=0D
+/**=0D
+ Create context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create context entry.=
=0D
+**/=0D
+EFI_STATUS=0D
+CreateContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTR=
Y_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CON=
TEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].RootEntryTable =3D (VTD_ROOT_ENTRY *)Buffe=
r;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId.I=
ndex.RootIndex];=0D
+ if (RootEntry->Bits.Present =3D=3D 0) {=0D
+ RootEntry->Bits.ContextTablePointerLo =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 12);=0D
+ RootEntry->Bits.ContextTablePointerHi =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 32);=0D
+ RootEntry->Bits.Present =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(R=
ootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi=
) ;=0D
+ ContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex];=0D
+ ContextEntry->Bits.TranslationType =3D 0;=0D
+ ContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n", mVtdUnitInform=
ation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.=
Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Roo=
tEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry table.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] MemoryBase The base of the memory.=0D
+ @param[in] MemoryLimit The limit of the memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntryTable (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 MemoryBase,=0D
+ IN UINT64 MemoryLimit,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Lvl5Start;=0D
+ UINTN Lvl5End;=0D
+ UINTN Lvl4PagesStart;=0D
+ UINTN Lvl4PagesEnd;=0D
+ UINTN Lvl4Start;=0D
+ UINTN Lvl4End;=0D
+ UINTN Lvl3Start;=0D
+ UINTN Lvl3End;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 EndAddress;=0D
+=0D
+ if (MemoryLimit =3D=3D 0) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ Lvl4PagesStart =3D 0;=0D
+ Lvl4PagesEnd =3D 0;=0D
+ Lvl4PtEntry =3D NULL;=0D
+ Lvl5PtEntry =3D NULL;=0D
+=0D
+ BaseAddress =3D ALIGN_VALUE_LOW(MemoryBase, SIZE_2MB);=0D
+ EndAddress =3D ALIGN_VALUE_UP(MemoryLimit, SIZE_2MB);=0D
+ DEBUG ((DEBUG_INFO,"CreateSecondLevelPagingEntryTable: BaseAddress - 0x%=
016lx, EndAddress - 0x%016lx\n", BaseAddress, EndAddress));=0D
+=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ SecondLevelPagingEntry =3D AllocateZeroPages (1);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry, EFI_PAG=
ES_TO_SIZE(1));=0D
+ }=0D
+=0D
+ //=0D
+ // If no access is needed, just create not present entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ return SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D RShiftU64 (EndAddress - 1, 48) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start, =
Lvl5End));=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+=0D
+ Lvl4PagesStart =3D (Lvl5Start<<9) | Lvl4Start;=0D
+ Lvl4PagesEnd =3D (Lvl5End<<9) | Lvl4End;=0D
+ DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", L=
vl4PagesStart, Lvl4PagesEnd));=0D
+=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ } else {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D Lvl5Start;=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, =
Lvl4End));=0D
+=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ }=0D
+=0D
+ for (Index5 =3D Lvl5Start; Index5 <=3D Lvl5End; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ Lvl5PtEntry[Index5].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index5));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl5PtEntry[Index5].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+ Lvl4Start =3D Lvl4PagesStart & 0x1FF;=0D
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {=0D
+ Lvl4End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;=0D
+ Lvl4PagesStart =3D (Index5+1)<<9;=0D
+ } else {=0D
+ Lvl4End =3D Lvl4PagesEnd & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\n=
", Index5, Lvl4Start, Lvl4End));=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D Lvl4Start; Index4 <=3D Lvl4End; Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ Lvl4PtEntry[Index4].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index4));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl3Start =3D RShiftU64 (BaseAddress, 30) & 0x1FF;=0D
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=3D EndAddres=
s) {=0D
+ Lvl3End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;=0D
+ } else {=0D
+ Lvl3End =3D RShiftU64 (EndAddress - 1, 30) & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n=
", Index4, Lvl3Start, Lvl3End));=0D
+=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D Lvl3Start; Index3 <=3D Lvl3End; Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ Lvl3PtEntry[Index3].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages =
(1);=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%=
x)!!!!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint6=
4, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_=
IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ Lvl2PtEntry[Index2].Uint64 =3D BaseAddress;=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuA=
ccess);=0D
+ Lvl2PtEntry[Index2].Bits.PageSize =3D 1;=0D
+ BaseAddress +=3D SIZE_2MB;=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UIN=
TN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN=
)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start], (UINTN)&=
Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex, =
SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess, Is5LevelPaging=
);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ if (mAbove4GMemoryLimit !=3D 0) {=0D
+ ASSERT (mAbove4GMemoryLimit > BASE_4GB);=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex=
, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess, Is5Le=
velPaging);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ }=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG((DEBUG_INFO, "CreateContextEntry - %d\n", Index));=0D
+=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.SMTS) {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));=0D
+ ASSERT(FALSE);=0D
+ Status =3D EFI_UNSUPPORTED;=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ } else {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ //=0D
+ // To compatible with pervious VTd engine=0D
+ // It was ECS(Extended Context Support) bit.=0D
+ //=0D
+ Status =3D CreateExtContextEntry (Index);=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ }=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR second level paging entry.=0D
+=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+DumpSecondLevelPagingEntry (=0D
+ IN VOID *SecondLevelPagingEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Index1;=0D
+ UINTN Lvl5IndexEnd;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl1PtEntry;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x, Is5LevelPagin=
g - %d\n", SecondLevelPagingEntry, Is5LevelPaging));=0D
+=0D
+ Lvl5IndexEnd =3D Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY) : 1;=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+=0D
+ for (Index5 =3D 0; Index5 < Lvl5IndexEnd; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n", Index=
5, Lvl5PtEntry[Index5].Uint64));=0D
+ }=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_EN=
TRY); Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index=
4, Lvl4PtEntry[Index4].Uint64));=0D
+ }=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_=
ENTRY); Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", In=
dex3, Lvl3PtEntry[Index3].Uint64));=0D
+ }=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ if (Lvl2PtEntry[Index2].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",=
Index2, Lvl2PtEntry[Index2].Uint64));=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Bits.PageSize =3D=3D 0) {=0D
+ Lvl1PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64=
BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.A=
ddressHi);=0D
+ for (Index1 =3D 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_P=
AGING_ENTRY); Index1++) {=0D
+ if (Lvl1PtEntry[Index1].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016=
lx\n", Index1, Lvl1PtEntry[Index1].Uint64));=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+}=0D
+=0D
+/**=0D
+ Invalid page entry.=0D
+=0D
+ @param VtdIndex The VTd engine index.=0D
+**/=0D
+VOID=0D
+InvalidatePageEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateVtdIOTLBGlobal (VtdIndex);=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D FALSE;=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D FALSE;=0D
+}=0D
+=0D
+#define VTD_PG_R BIT0=0D
+#define VTD_PG_W BIT1=0D
+#define VTD_PG_X BIT2=0D
+#define VTD_PG_EMT (BIT3 | BIT4 | BIT5)=0D
+#define VTD_PG_TM (BIT62)=0D
+=0D
+#define VTD_PG_PS BIT7=0D
+=0D
+#define PAGE_PROGATE_BITS (VTD_PG_TM | VTD_PG_EMT | VTD_PG_W | VT=
D_PG_R)=0D
+=0D
+#define PAGING_4K_MASK 0xFFF=0D
+#define PAGING_2M_MASK 0x1FFFFF=0D
+#define PAGING_1G_MASK 0x3FFFFFFF=0D
+=0D
+#define PAGING_VTD_INDEX_MASK 0x1FF=0D
+=0D
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull=0D
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull=0D
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull=0D
+=0D
+typedef enum {=0D
+ PageNone,=0D
+ Page4K,=0D
+ Page2M,=0D
+ Page1G,=0D
+} PAGE_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ PAGE_ATTRIBUTE Attribute;=0D
+ UINT64 Length;=0D
+ UINT64 AddressMask;=0D
+} PAGE_ATTRIBUTE_TABLE;=0D
+=0D
+PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D {=0D
+ {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},=0D
+ {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},=0D
+ {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},=0D
+};=0D
+=0D
+/**=0D
+ Return length according to page attributes.=0D
+=0D
+ @param[in] PageAttributes The page attribute of the page entry.=0D
+=0D
+ @return The length of page entry.=0D
+**/=0D
+UINTN=0D
+PageAttributeToLength (=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ for (Index =3D 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttrib=
uteTable[0]); Index++) {=0D
+ if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) {=0D
+ return (UINTN)mPageAttributeTable[Index].Length;=0D
+ }=0D
+ }=0D
+ return 0;=0D
+}=0D
+=0D
+/**=0D
+ Return page table entry to match the address.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd e=
ngine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in V=
Td table for the device.=0D
+ @param[in] Address The address to be checked.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+ @param[out] PageAttributes The page attribute of the page ent=
ry.=0D
+=0D
+ @return The page entry.=0D
+**/=0D
+VOID *=0D
+GetSecondLevelPageTableEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN PHYSICAL_ADDRESS Address,=0D
+ IN BOOLEAN Is5LevelPaging,=0D
+ OUT PAGE_ATTRIBUTE *PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index1;=0D
+ UINTN Index2;=0D
+ UINTN Index3;=0D
+ UINTN Index4;=0D
+ UINTN Index5;=0D
+ UINT64 *L1PageTable;=0D
+ UINT64 *L2PageTable;=0D
+ UINT64 *L3PageTable;=0D
+ UINT64 *L4PageTable;=0D
+ UINT64 *L5PageTable;=0D
+=0D
+ Index5 =3D ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;=0D
+ Index4 =3D ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;=0D
+ Index3 =3D ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;=0D
+ Index2 =3D ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;=0D
+ Index1 =3D ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ L5PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ L5PageTable[Index5] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\n=
", Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5], SIZE_4KB=
);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *=
)&L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5], sizeof(=
L5PageTable[Index5]));=0D
+ }=0D
+ L4PageTable =3D (UINT64 *)(UINTN)(L5PageTable[Index5] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ } else {=0D
+ L4PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ L4PageTable[Index4] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n",=
Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L4PageTable[Index4], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L4PageTable[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L4PageTable[Index4], sizeof(L4=
PageTable[Index4]));=0D
+ }=0D
+=0D
+ L3PageTable =3D (UINT64 *)(UINTN)(L4PageTable[Index4] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ L3PageTable[Index3] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!=
!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L3PageTable[Index3], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L3PageTable[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L3PageTable[Index3], sizeof(L3=
PageTable[Index3]));=0D
+ }=0D
+ if ((L3PageTable[Index3] & VTD_PG_PS) !=3D 0) {=0D
+ // 1G=0D
+ *PageAttribute =3D Page1G;=0D
+ return &L3PageTable[Index3];=0D
+ }=0D
+=0D
+ L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L2PageTable[Index2] =3D=3D 0) {=0D
+ L2PageTable[Index2] =3D Address & PAGING_2M_ADDRESS_MASK_64;=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L2PageTable[Index2], 0);=0D
+ L2PageTable[Index2] |=3D VTD_PG_PS;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L2PageTable[Index2], sizeof(L2=
PageTable[Index2]));=0D
+ }=0D
+ if ((L2PageTable[Index2] & VTD_PG_PS) !=3D 0) {=0D
+ // 2M=0D
+ *PageAttribute =3D Page2M;=0D
+ return &L2PageTable[Index2];=0D
+ }=0D
+=0D
+ // 4k=0D
+ L1PageTable =3D (UINT64 *)(UINTN)(L2PageTable[Index2] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if ((L1PageTable[Index1] =3D=3D 0) && (Address !=3D 0)) {=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ *PageAttribute =3D Page4K;=0D
+ return &L1PageTable[Index1];=0D
+}=0D
+=0D
+/**=0D
+ Modify memory attributes of page entry.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[out] IsModified TRUE means page table modified. FALSE mean=
s page table not modified.=0D
+**/=0D
+VOID=0D
+ConvertSecondLevelPageEntryAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN UINT64 IoMmuAccess,=0D
+ OUT BOOLEAN *IsModified=0D
+ )=0D
+{=0D
+ UINT64 CurrentPageEntry;=0D
+ UINT64 NewPageEntry;=0D
+=0D
+ CurrentPageEntry =3D PageEntry->Uint64;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry));=0D
+ NewPageEntry =3D PageEntry->Uint64;=0D
+ if (CurrentPageEntry !=3D NewPageEntry) {=0D
+ *IsModified =3D TRUE;=0D
+ DEBUG ((DEBUG_VERBOSE, "ConvertSecondLevelPageEntryAttribute 0x%lx", C=
urrentPageEntry));=0D
+ DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));=0D
+ } else {=0D
+ *IsModified =3D FALSE;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ This function returns if there is need to split page entry.=0D
+=0D
+ @param[in] BaseAddress The base address to be checked.=0D
+ @param[in] Length The length to be checked.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+=0D
+ @retval SplitAttributes on if there is need to split page entry.=0D
+**/=0D
+PAGE_ATTRIBUTE=0D
+NeedSplitPage (=0D
+ IN PHYSICAL_ADDRESS BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINT64 PageEntryLength;=0D
+=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+=0D
+ if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D Pag=
eEntryLength)) {=0D
+ return PageNone;=0D
+ }=0D
+=0D
+ if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) {=0D
+ return Page4K;=0D
+ }=0D
+=0D
+ return Page2M;=0D
+}=0D
+=0D
+/**=0D
+ This function splits one page entry to small page entries.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry to be splitted.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+ @param[in] SplitAttribute How to split the page entry.=0D
+=0D
+ @retval RETURN_SUCCESS The page entry is splitted.=0D
+ @retval RETURN_UNSUPPORTED The page entry does not support to be =
splitted.=0D
+ @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.=0D
+**/=0D
+RETURN_STATUS=0D
+SplitSecondLevelPage (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN PAGE_ATTRIBUTE PageAttribute,=0D
+ IN PAGE_ATTRIBUTE SplitAttribute=0D
+ )=0D
+{=0D
+ UINT64 BaseAddress;=0D
+ UINT64 *NewPageEntry;=0D
+ UINTN Index;=0D
+=0D
+ ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G);=0D
+=0D
+ if (PageAttribute =3D=3D Page2M) {=0D
+ //=0D
+ // Split 2M to 4K=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page4K);=0D
+ if (SplitAttribute =3D=3D Page4K) {=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_2M_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | (PageEn=
try->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else if (PageAttribute =3D=3D Page1G) {=0D
+ //=0D
+ // Split 1G to 2M=0D
+ // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K =
to get more compact page table.=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K);=
=0D
+ if ((SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K)) {=
=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_1G_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | VTD_PG_=
PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory on second level page entry=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetSecondLevelPagingAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry;=0D
+ PAGE_ATTRIBUTE PageAttribute;=0D
+ UINTN PageEntryLength;=0D
+ PAGE_ATTRIBUTE SplitAttribute;=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN IsEntryModified;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetSecondLevelPagingAttribute (%d) (0x%016lx - 0x=
%016lx : %x) \n", VtdIndex, BaseAddress, Length, IoMmuAccess));=0D
+ DEBUG ((DEBUG_VERBOSE," SecondLevelPagingEntry Base - 0x%x\n", SecondLe=
velPagingEntry));=0D
+=0D
+ if (BaseAddress !=3D ALIGN_VALUE(BaseAddress, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ if (Length !=3D ALIGN_VALUE(Length, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ while (Length !=3D 0) {=0D
+ PageEntry =3D GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagin=
gEntry, BaseAddress, mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAtt=
ribute);=0D
+ if (PageEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+ SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageAttribute);=
=0D
+ if (SplitAttribute =3D=3D PageNone) {=0D
+ ConvertSecondLevelPageEntryAttribute (VtdIndex, PageEntry, IoMmuAcce=
ss, &IsEntryModified);=0D
+ if (IsEntryModified) {=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ }=0D
+ //=0D
+ // Convert success, move to next=0D
+ //=0D
+ BaseAddress +=3D PageEntryLength;=0D
+ Length -=3D PageEntryLength;=0D
+ } else {=0D
+ Status =3D SplitSecondLevelPage (VtdIndex, PageEntry, PageAttribute,=
SplitAttribute);=0D
+ if (RETURN_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ //=0D
+ // Just split current page=0D
+ // Convert success in next around=0D
+ //=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (SecondLevelPagingEntry !=3D NULL) {=0D
+ Status =3D SetSecondLevelPagingAttribute (VtdIndex, DomainIdentifier, =
SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);=0D
+ }=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ EFI_STATUS Status;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+ UINTN PciDataIndex;=0D
+ UINT16 DomainIdentifier;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetAccessAttribute (S%04x B%02x D%02x F%02x) (0x%=
016lx - 0x%08x, %x)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function, BaseAddress, (UINTN)Length, IoMmuAccess));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"SetAccessAttribute - Pci device (S%04x B%02x D%02=
x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceData[PciDataIndex]=
.AccessCount++;=0D
+ //=0D
+ // DomainId should not be 0.=0D
+ //=0D
+ DomainIdentifier =3D (UINT16)(PciDataIndex + 1);=0D
+=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ if (ExtContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT3=
2) Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT3=
2) RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtC=
ontextEntry));=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
VtdIndex].ExtRootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=
=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtCont=
extEntry->Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry->Bits.S=
econdLevelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ if (ContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) =
Pt;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) =
RShiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*Context=
Entry));=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Vtd=
Index].RootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(Context=
Entry->Bits.SecondLevelPageTranslationPointerLo, ContextEntry->Bits.SecondL=
evelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Do not update FixedSecondLevelPagingEntry=0D
+ //=0D
+ if (SecondLevelPagingEntry !=3D mVtdUnitInformation[VtdIndex].FixedSecon=
dLevelPagingEntry) {=0D
+ Status =3D SetPageAttribute (=0D
+ VtdIndex,=0D
+ DomainIdentifier,=0D
+ SecondLevelPagingEntry,=0D
+ BaseAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR,"SetPageAttribute - %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ InvalidatePageEntry (VtdIndex);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"AlwaysEnablePageAttribute (S%04x B%02x D%02x F%02x)\=
n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Functio=
n));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"AlwaysEnablePageAttribute - Pci device (S%04x B%0=
2x D%02x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.De=
vice, SourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D=3D 0) =
{=0D
+ DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex));=
=0D
+ mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D CreateSe=
condLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCES=
S_WRITE, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ }=0D
+=0D
+ SecondLevelPagingEntry =3D mVtdUnitInformation[VtdIndex].FixedSecondLeve=
lPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32)=
Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32)=
RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdU=
nitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtCon=
textEntry));=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) Pt=
;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) RS=
hiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdUnit=
Information[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEn=
try));=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTableEx.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDx=
e/TranslationTableEx.c
new file mode 100644
index 000000000..c07afaf2b
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
TableEx.c
@@ -0,0 +1,108 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_=
ENTRY_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD=
_CONTEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].ExtRootEntryTable =3D (VTD_EXT_ROOT_ENTRY =
*)Buffer;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[Sour=
ceId.Index.RootIndex];=0D
+ if (ExtRootEntry->Bits.LowerPresent =3D=3D 0) {=0D
+ ExtRootEntry->Bits.LowerContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12);=0D
+ ExtRootEntry->Bits.LowerContextTablePointerHi =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 32);=0D
+ ExtRootEntry->Bits.LowerPresent =3D 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12) + 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerHi =3D (UINT32) RShiftU6=
4 (RShiftU64 ((UINT64)(UINTN)Buffer, 12) + 1, 20);=0D
+ ExtRootEntry->Bits.UpperPresent =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_AD=
DRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.Low=
erContextTablePointerHi) ;=0D
+ ExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.ContextIndex]=
;=0D
+ ExtContextEntry->Bits.TranslationType =3D 0;=0D
+ ExtContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ExtContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n", mVtdUnitInfor=
mation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId=
.Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+=0D
+=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Ext=
RootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdR=
eg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
new file mode 100644
index 000000000..dd0c49698
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
@@ -0,0 +1,757 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#define VTD_CAP_REG_NFR_MAX (256)=0D
+=0D
+UINTN mVtdUnitNumber =3D 0;=0D
+VTD_UNIT_INFORMATION *mVtdUnitInformation =3D NULL;=0D
+VTD_REGESTER_INFO *mVtdRegsInfoBuffer =3D NULL;=0D
+=0D
+BOOLEAN mVtdEnabled;=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *)Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_IQA_REG IqaReg;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[VtdIndex];=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ if (VtdUnitInfo->VerReg.Bits.Major <=3D 5) {=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for eng=
ine [%d]\n", VtdIndex));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ECapReg.Bits.QI =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations i=
nterface for engine [%d]\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 1;=0D
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n=
", VtdIndex));=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ if ((Reg32 & B_GSTS_REG_QIES) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n"));=
=0D
+=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitBaseAddress);=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the Invalidation Queue Tail Register to zero.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);=0D
+=0D
+ //=0D
+ // Setup the IQ address, size and descriptor width through the Invalidat=
ion Queue Address Register=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ VtdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <=
< (VTD_INVALIDATION_QUEUE_SIZE + 7)));=0D
+ VtdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VtdUni=
tInfo->QiDescBufferSize));=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"))=
;=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ERROR_OUT=
_OF_RESOURCES, VtdUnitBaseAddress);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VtdUnitInfo=
->QiDescBufferSize));=0D
+ //=0D
+ // 4KB Aligned address=0D
+ //=0D
+ IqaReg.Uint64 =3D (UINT64) (UINTN) VtdUnitInfo->QiDescBuffer;=0D
+ IqaReg.Bits.DW =3D VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH;=0D
+ IqaReg.Bits.QS =3D VTD_INVALIDATION_QUEUE_SIZE;=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ DEBUG ((DEBUG_INFO, "IQA_REG =3D 0x%lx, IQH_REG =3D 0x%lx\n", IqaReg.Uin=
t64, MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));=0D
+=0D
+ //=0D
+ // Enable the queued invalidation interface through the Global Command R=
egister.=0D
+ // When enabled, hardware sets the QIES field in the Global Status Regis=
ter.=0D
+ //=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 |=3D B_GMCD_REG_QIE;=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG =3D =
0x%x\n", Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ENABLE, VtdUn=
itBaseAddress);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+SubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN QI_256_DESC *Desc=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_REGESTER_QI_INFO RegisterQi;=0D
+=0D
+ Status =3D VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress,=
Desc, FALSE);=0D
+ if (Status =3D=3D EFI_DEVICE_ERROR) {=0D
+ RegisterQi.BaseAddress =3D VtdUnitBaseAddress;=0D
+ RegisterQi.FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG=
);;=0D
+ RegisterQi.IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_R=
EG);=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_QI, &Register=
Qi, sizeof (VTD_REGESTER_QI_INFO));=0D
+=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, RegisterQi.FstsReg & (B_=
FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE));=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ R_CCMD_REG);=0D
+ if ((Reg64 & B_CCMD_REG_ICC) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC i=
s set for VTD(%d)\n",VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));=0D
+ Reg64 |=3D (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD=
_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + R_CCMD_REG);=0D
+ } while ((Reg64 & B_CCMD_REG_ICC) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC=
_GRAN(1) | QI_CC_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=0D
+ if ((Reg64 & B_IOTLB_REG_IVT) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set =
for VTD(%d)\n", VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));=0D
+ Reg64 |=3D (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdU=
nitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=
=0D
+ } while ((Reg64 & B_IOTLB_REG_IVT) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtd=
UnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVt=
dUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TY=
PE;=0D
+ QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0=
);=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (!mVtdEnabled) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext) {=0D
+ InvalidateContextCache (VtdIndex);=0D
+ }=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN DomainNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ if (mVtdRegsInfoBuffer =3D=3D NULL) {=0D
+ mVtdRegsInfoBuffer =3D AllocateZeroPool (sizeof (VTD_REGESTER_INFO) + =
sizeof (VTD_UINT128) * VTD_CAP_REG_NFR_MAX);=0D
+ ASSERT (mVtdRegsInfoBuffer !=3D NULL);=0D
+ }=0D
+=0D
+ //=0D
+ // Dump VTd error before DXE phase=0D
+ //=0D
+ DumpVtdIfError ();=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));=0D
+ mVtdUnitInformation[Index].VerReg.Uint32 =3D MmioRead32 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_VER_REG);=0D
+ DumpVtdVerRegs (&mVtdUnitInformation[Index].VerReg);=0D
+ mVtdUnitInformation[Index].CapReg.Uint64 =3D MmioRead64 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_CAP_REG);=0D
+ DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);=0D
+ mVtdUnitInformation[Index].ECapReg.Uint64 =3D MmioRead64 (mVtdUnitInfo=
rmation[Index].VtdUnitBaseAddress + R_ECAP_REG);=0D
+ DumpVtdECapRegs (&mVtdUnitInformation[Index].ECapReg);=0D
+=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) =3D=3D 0) {=
=0D
+ DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !=
!!!\n", Index));=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) =3D=
=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on V=
TD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));=0D
+ return ;=0D
+ }=0D
+=0D
+ DomainNumber =3D (UINTN)1 << (UINT8)((UINTN)mVtdUnitInformation[Index]=
.CapReg.Bits.ND * 2 + 4);=0D
+ if (mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumber >=3D=
DomainNumber) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >=3D DomainNumber(=
0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumbe=
r, DomainNumber));=0D
+ return ;=0D
+ }=0D
+=0D
+ Status =3D PerpareCacheInvalidationInterface(Index);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT(FALSE);=0D
+ return;=0D
+ }=0D
+ }=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Disable PMR in all VTd engine.=0D
+**/=0D
+VOID=0D
+DisablePmr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DisablePmr\n"));=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ Status =3D VtdLibDisablePmr (mVtdUnitInformation[Index].VtdUnitBaseAdd=
ress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_PMR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, Status);=0D
+ }=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Update Root Table Address Register=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] EnableADM TRUE - Enable ADM in TTM bits=0D
+**/=0D
+VOID=0D
+UpdateRootTableAddressRegister (=0D
+ IN UINTN VtdIndex,=0D
+ IN BOOLEAN EnableADM=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D NULL) {=0D
+ DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Vt=
dIndex].ExtRootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTab=
le | (EnableADM ? V_RTADDR_REG_TTM_ADM : BIT11);=0D
+ } else {=0D
+ DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[VtdIn=
dex].RootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable =
| (EnableADM ? V_RTADDR_REG_TTM_ADM : 0);=0D
+ }=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR=
_REG, Reg64);=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ BOOLEAN TEWasEnabled;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitBaseAddress =3D mVtdUnitInformation[Index].VtdUnitBaseAddress;=
=0D
+ DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] BAR [0x%x]\n", =
Index, VtdUnitBaseAddress));=0D
+=0D
+ //=0D
+ // Check TE was enabled or not.=0D
+ //=0D
+ TEWasEnabled =3D ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GS=
TS_REG_TE) =3D=3D B_GSTS_REG_TE);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ //=0D
+ // For implementations reporting Enhanced SRTP Support (ESRTPS) fiel=
d as=0D
+ // Clear in the Capability register, software must not modify this f=
ield while=0D
+ // DMA remapping is active (TES=3D1 in Global Status register).=0D
+ //=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable ADM=0D
+ //=0D
+ UpdateRootTableAddressRegister (Index, TRUE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+=0D
+ DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_T=
E);=0D
+=0D
+ } else {=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ InvalidateContextCache (Index);=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ InvalidateIOTLB (Index);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_ENABLE_DMAR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, 0);=0D
+ }=0D
+=0D
+ //=0D
+ // Need disable PMR, since we already setup translation table.=0D
+ //=0D
+ DisablePmr ();=0D
+=0D
+ mVtdEnabled =3D TRUE;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN SubIndex;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+=0D
+ VtdLibDisableDmar (VtdUnitInfo->VtdUnitBaseAddress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_DMAR, VtdUnitInfo->VtdUnitBaseAddre=
ss, 0);=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation !=3D 0) {=0D
+ //=0D
+ // Disable queued invalidation interface.=0D
+ //=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitInfo->VtdUnitBaseAd=
dress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_DISABLE, =
VtdUnitInfo->VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Free descriptor queue memory=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer !=3D NULL) {=0D
+ FreePages(VtdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VtdUnitInf=
o->QiDescBufferSize));=0D
+ VtdUnitInfo->QiDescBuffer =3D NULL;=0D
+ VtdUnitInfo->QiDescBufferSize =3D 0;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ }=0D
+ }=0D
+=0D
+ mVtdEnabled =3D FALSE;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+ DEBUG((DEBUG_INFO, "engine [%d] access\n", Index));=0D
+ for (SubIndex =3D 0; SubIndex < VtdUnitInfo->PciDeviceInfo->PciDeviceD=
ataNumber; SubIndex++) {=0D
+ DEBUG ((DEBUG_INFO, " PCI S%04X B%02x D%02x F%02x - %d\n",=0D
+ VtdUnitInfo->Segment,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Bus,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Device,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Function,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].AccessCount=0D
+ ));=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, " VerReg - 0x%x\n", VerReg->Uint32));=0D
+ DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major));=0D
+ DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ )=0D
+{=0D
+ DEBUG((DEBUG_INFO, " CapReg - 0x%x\n", CapReg->Uint64));=0D
+ DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND));=0D
+ DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL));=0D
+ DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF));=0D
+ DEBUG((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR));=0D
+ DEBUG((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR));=0D
+ DEBUG((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM));=0D
+ DEBUG((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW));=0D
+ DEBUG((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW));=0D
+ DEBUG((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR));=0D
+ DEBUG((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO));=0D
+ DEBUG((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS));=0D
+ DEBUG((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI));=0D
+ DEBUG((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR));=0D
+ DEBUG((DEBUG_INFO, " MAMV - 0x%x\n", CapReg->Bits.MAMV));=0D
+ DEBUG((DEBUG_INFO, " DWD - 0x%x\n", CapReg->Bits.DWD));=0D
+ DEBUG((DEBUG_INFO, " DRD - 0x%x\n", CapReg->Bits.DRD));=0D
+ DEBUG((DEBUG_INFO, " FL1GP - 0x%x\n", CapReg->Bits.FL1GP));=0D
+ DEBUG((DEBUG_INFO, " PI - 0x%x\n", CapReg->Bits.PI));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd extended capability registers.=0D
+=0D
+ @param[in] ECapReg The extended capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdECapRegs (=0D
+ IN VTD_ECAP_REG *ECapReg=0D
+ )=0D
+{=0D
+ DEBUG((DEBUG_INFO, " ECapReg - 0x%lx\n", ECapReg->Uint64));=0D
+ DEBUG((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C));=0D
+ DEBUG((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI));=0D
+ DEBUG((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT));=0D
+ DEBUG((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR));=0D
+ DEBUG((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM));=0D
+ DEBUG((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT));=0D
+ DEBUG((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC));=0D
+ DEBUG((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO));=0D
+ DEBUG((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV));=0D
+ DEBUG((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS));=0D
+ DEBUG((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST));=0D
+ DEBUG((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID));=0D
+ DEBUG((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS));=0D
+ DEBUG((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS));=0D
+ DEBUG((DEBUG_INFO, " SRS - 0x%x\n", ECapReg->Bits.SRS));=0D
+ DEBUG((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS));=0D
+ DEBUG((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS));=0D
+ DEBUG((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS));=0D
+ DEBUG((DEBUG_INFO, " SMTS - 0x%x\n", ECapReg->Bits.SMTS));=0D
+ DEBUG((DEBUG_INFO, " ADMS - 0x%x\n", ECapReg->Bits.ADMS));=0D
+ DEBUG((DEBUG_INFO, " PDS - 0x%x\n", ECapReg->Bits.PDS));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegs (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ VTD_REGESTER_INFO *VtdRegInfo;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_CAP_REG CapReg;=0D
+=0D
+ if (mVtdRegsInfoBuffer =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VtdRegInfo =3D mVtdRegsInfoBuffer;=0D
+ VtdRegInfo->BaseAddress =3D VtdUnitBaseAddress;=0D
+ VtdRegInfo->VerReg =3D MmioRead32 (VtdUnitBaseAddress + R_VER_REG);=
=0D
+ VtdRegInfo->CapReg =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=
=0D
+ VtdRegInfo->EcapReg =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG)=
;=0D
+ VtdRegInfo->GstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG)=
;=0D
+ VtdRegInfo->RtaddrReg =3D MmioRead64 (VtdUnitBaseAddress + R_RTADDR_RE=
G);=0D
+ VtdRegInfo->CcmdReg =3D MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG)=
;=0D
+ VtdRegInfo->FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG)=
;=0D
+ VtdRegInfo->FectlReg =3D MmioRead32 (VtdUnitBaseAddress + R_FECTL_REG=
);=0D
+ VtdRegInfo->FedataReg =3D MmioRead32 (VtdUnitBaseAddress + R_FEDATA_RE=
G);=0D
+ VtdRegInfo->FeaddrReg =3D MmioRead32 (VtdUnitBaseAddress + R_FEADDR_RE=
G);=0D
+ VtdRegInfo->FeuaddrReg =3D MmioRead32 (VtdUnitBaseAddress + R_FEUADDR_R=
EG);=0D
+ VtdRegInfo->IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_RE=
G);=0D
+=0D
+ CapReg.Uint64 =3D VtdRegInfo->CapReg;=0D
+ for (VtdRegInfo->FrcdRegNum =3D 0; VtdRegInfo->FrcdRegNum < (UINT16) Cap=
Reg.Bits.NFR + 1; VtdRegInfo->FrcdRegNum++) {=0D
+ VtdRegInfo->FrcdReg[VtdRegInfo->FrcdRegNum].Uint64Lo =3D MmioRead64 (V=
tdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (VtdRegInfo->FrcdRegNum * 16)=
+ R_FRCD_REG));=0D
+ VtdRegInfo->FrcdReg[VtdRegInfo->FrcdRegNum].Uint64Hi =3D MmioRead64 (V=
tdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (VtdRegInfo->FrcdRegNum * 16)=
+ R_FRCD_REG + sizeof(UINT64)));=0D
+ }=0D
+=0D
+ ECapReg.Uint64 =3D VtdRegInfo->EcapReg;=0D
+ VtdRegInfo->IvaReg =3D MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IR=
O * 16) + R_IVA_REG);=0D
+ VtdRegInfo->IotlbReg =3D MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.=
IRO * 16) + R_IOTLB_REG);=0D
+=0D
+ DEBUG((DEBUG_INFO, "#### DumpVtdRegs(0x%016lx) Begin ####\n", VtdUnitBas=
eAddress));=0D
+=0D
+ VtdLibDumpVtdRegsAll (NULL, NULL, VtdRegInfo);=0D
+=0D
+ DEBUG((DEBUG_INFO, "#### DumpVtdRegs(0x%016lx) End ####\n", VtdUnitBaseA=
ddress));=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_REGISTER, VTDLOG_REGISTER_ALL, (VOID *) V=
tdRegInfo, sizeof (VTD_REGESTER_INFO) + sizeof (VTD_UINT128) * (VtdRegInfo-=
+=0D
+/**=0D
+ Dump VTd registers for all VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegsAll (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ DumpVtdRegs (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Num;=0D
+ UINTN Index;=0D
+ VTD_FRCD_REG FrcdReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ UINT32 Reg32;=0D
+ BOOLEAN HasError;=0D
+=0D
+ for (Num =3D 0; Num < mVtdUnitNumber; Num++) {=0D
+ HasError =3D FALSE;=0D
+ Reg32 =3D MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_=
FSTS_REG);=0D
+ if (Reg32 !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+ Reg32 =3D MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_=
FECTL_REG);=0D
+ if ((Reg32 & BIT30) !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddr=
ess + R_CAP_REG);=0D
+ for (Index =3D 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[0] =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnitBa=
seAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnitBa=
seAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UI=
NT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+ }=0D
+=0D
+ if (HasError) {=0D
+ REPORT_STATUS_CODE (EFI_ERROR_CODE, PcdGet32 (PcdErrorCodeVTdError))=
;=0D
+ DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));=0D
+ DumpVtdRegs (Num);=0D
+ DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));=0D
+ //=0D
+ // Clear=0D
+ //=0D
+ for (Index =3D 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnit=
BaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(=
UINT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ //=0D
+ // Software writes the value read from this field (F) to Clear i=
t.=0D
+ //=0D
+ MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((Cap=
Reg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.U=
int64[1]);=0D
+ }=0D
+ }=0D
+ MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_RE=
G, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG));=
=0D
+ }=0D
+ }=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Dmar=
Table.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/DmarTab=
le.c
new file mode 100644
index 000000000..5672f4014
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/DmarTable.c
@@ -0,0 +1,301 @@
+/** @file=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/HobLib.h>=0D
+#include <Library/PciSegmentLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <IndustryStandard/Pci.h>=0D
+#include <Protocol/IoMmu.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+/**=0D
+ Dump DMAR DeviceScopeEntry.=0D
+=0D
+ @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry=0D
+**/=0D
+VOID=0D
+DumpDmarDeviceScopeEntry (=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry=0D
+ )=0D
+{=0D
+ UINTN PciPathNumber;=0D
+ UINTN PciPathIndex;=0D
+ EFI_ACPI_DMAR_PCI_PATH *PciPath;=0D
+=0D
+ if (DmarDeviceScopeEntry =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " * DMA-Remapping Device Scope Entry Structure =
*\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ (sizeof (UINTN) =3D=3D sizeof (UINT64)) ?=0D
+ " DMAR Device Scope Entry address ...................... 0x%016lx\n=
" :=0D
+ " DMAR Device Scope Entry address ...................... 0x%08x\n",=
=0D
+ DmarDeviceScopeEntry=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Device Scope Entry Type ............................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Type=0D
+ ));=0D
+ switch (DmarDeviceScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " PCI Endpoint Device\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " PCI Sub-hierachy\n"=0D
+ ));=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................. 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Length=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Enumeration ID ..................................... 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->EnumerationId=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Starting Bus Number ................................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->StartBusNumber=0D
+ ));=0D
+=0D
+ PciPathNumber =3D (DmarDeviceScopeEntry->Length - sizeof (EFI_ACPI_DMAR_=
DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof (EFI_ACPI_DMAR_PCI_PATH);=0D
+ PciPath =3D (EFI_ACPI_DMAR_PCI_PATH *) (DmarDeviceScopeEntry + 1);=0D
+ for (PciPathIndex =3D 0; PciPathIndex < PciPathNumber; PciPathIndex++) {=
=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Device ............................................. 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Device=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Function ........................................... 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Function=0D
+ ));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n\n"=0D
+ ));=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR DRHD table.=0D
+=0D
+ @param[in] Drhd DMAR DRHD table=0D
+**/=0D
+VOID=0D
+DumpDmarDrhd (=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN DrhdLen;=0D
+=0D
+ if (Drhd =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " * DMA-Remapping Hardware Definition Structure =
*\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ (sizeof (UINTN) =3D=3D sizeof (UINT64)) ?=0D
+ " DRHD address ........................................... 0x%016lx\n=
" :=0D
+ " DRHD address ........................................... 0x%08x\n",=
=0D
+ Drhd=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Drhd->Header.Type=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Drhd->Header.Length=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Drhd->Flags=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " INCLUDE_PCI_ALL .................................... 0x%02x\n",=
=0D
+ Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Drhd->SegmentNumber=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Register Base Address ................................ 0x%016lx\n=
",=0D
+ Drhd->RegisterBaseAddress=0D
+ ));=0D
+=0D
+ DrhdLen =3D Drhd->Header.Length - sizeof (EFI_ACPI_DMAR_DRHD_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Drhd + 1);=0D
+ while (DrhdLen > 0) {=0D
+ DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);=0D
+ DrhdLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*) ((UINTN) DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+DumpAcpiDMAR (=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ INTN DmarLen;=0D
+=0D
+ if (Dmar =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "* DMAR Table =
*\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ (sizeof (UINTN) =3D=3D sizeof (UINT64)) ?=0D
+ "DMAR address ............................................. 0x%016lx\n=
" :=0D
+ "DMAR address ............................................. 0x%08x\n",=
=0D
+ Dmar=0D
+ ));=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Table Contents:\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Host Address Width ................................... 0x%02x\n",=
=0D
+ Dmar->HostAddressWidth=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Dmar->Flags=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " INTR_REMAP ......................................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG=0D
+ ));=0D
+=0D
+ DmarLen =3D Dmar->Header.Length - sizeof (EFI_ACPI_DMAR_HEADER);=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) (Dmar + 1);=0D
+ while (DmarLen > 0) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarLen -=3D DmarHeader->Length;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader =
+ DmarHeader->Length);=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n\n"=0D
+ ));=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @param[in] AcpiDmarTable DMAR ACPI table=0D
+ @param[in] Callback Callback function for handle DRHD=0D
+ @param[in] Context Callback function Context=0D
+=0D
+ @return the VTd engine number.=0D
+=0D
+**/=0D
+UINTN=0D
+ParseDmarAcpiTableDrhd (=0D
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,=0D
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ UINTN VtdIndex;=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTabl=
e + 1));=0D
+=0D
+ while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ if (Callback !=3D NULL) {=0D
+ Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHea=
der);=0D
+ }=0D
+ VtdIndex++;=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader =
+ DmarHeader->Length);=0D
+ }=0D
+=0D
+ return VtdIndex;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/I=
ntelVTdCorePei.c
new file mode 100644
index 000000000..0160c3604
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.c
@@ -0,0 +1,1099 @@
+/** @file=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/PeiServicesLib.h>=0D
+#include <Library/HobLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <Ppi/IoMmu.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Ppi/MemoryDiscovered.h>=0D
+#include <Ppi/EndOfPeiPhase.h>=0D
+#include <Guid/VtdPmrInfoHob.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+#define VTD_UNIT_MAX 64=0D
+=0D
+EFI_GUID mVTdInfoGuid =3D {=0D
+ 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x=
82 }=0D
+};=0D
+=0D
+EFI_GUID mDmaBufferInfoGuid =3D {=0D
+ 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, =
0x39 }=0D
+};=0D
+=0D
+#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ EDKII_IOMMU_OPERATION Operation;=0D
+ UINTN NumberOfBytes;=0D
+ EFI_PHYSICAL_ADDRESS HostAddress;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+} MAP_INFO;=0D
+=0D
+/**=0D
+ Allocate memory buffer for VTd log events.=0D
+=0D
+ @param[in] MemorySize Required memory buffer size.=0D
+=0D
+ @retval Buffer address=0D
+=0D
+**/=0D
+UINT8 *=0D
+EFIAPI=0D
+VTdLogAllocMemory (=0D
+ IN CONST UINT32 MemorySize=0D
+ )=0D
+{=0D
+ VOID *HobPtr;=0D
+ VTDLOG_PEI_BUFFER_HOB *BufferHob;=0D
+ UINT8 *ReturnBuffer;=0D
+=0D
+ ReturnBuffer =3D NULL;=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ BufferHob =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ if (BufferHob->PostMemBuffer !=3D 0) {=0D
+ //=0D
+ // Post-memory phase=0D
+ //=0D
+ if ((BufferHob->PostMemBufferUsed + MemorySize) < PcdGet32 (PcdVTdPe=
iPostMemLogBufferSize)) {=0D
+ ReturnBuffer =3D &((UINT8 *) (UINTN) BufferHob->PostMemBuffer)[Buf=
ferHob->PostMemBufferUsed];=0D
+ BufferHob->PostMemBufferUsed +=3D MemorySize;=0D
+ } else {=0D
+ BufferHob->VtdLogPeiError |=3D VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return ReturnBuffer;=0D
+}=0D
+=0D
+/**=0D
+ Add the VTd log event in post memory phase.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM *Item;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_PEI_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ Item =3D (VTDLOG_EVENT_2PARAM *) VTdLogAllocMemory (sizeof (VTDLOG_EVENT=
_2PARAM));=0D
+ if (Item !=3D NULL) {=0D
+ Item->Data1 =3D Data1;=0D
+ Item->Data2 =3D Data2;=0D
+ Item->Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item->Header.LogType =3D (UINT64) (1 << EventType);=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_CONTEXT *Item;=0D
+ UINT32 EventSize;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_PEI_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ EventSize =3D sizeof (VTDLOG_EVENT_CONTEXT) + DataSize - 1;=0D
+=0D
+ Item =3D (VTDLOG_EVENT_CONTEXT *) VTdLogAllocMemory (EventSize);=0D
+ if (Item !=3D NULL) {=0D
+ Item->Param =3D Param;=0D
+ CopyMem (Item->Data, Data, DataSize);=0D
+=0D
+ Item->Header.DataSize =3D EventSize;=0D
+ Item->Header.LogType =3D (UINT64) (1 << EventType);=0D
+ Item->Header.Timestamp =3D AsmReadTsc (); =0D
+ }=0D
+}=0D
+/**=0D
+ Add the VTd log event in pre-memory phase.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Mode Pre-memory DMA protection mode.=0D
+ @param[in] Status Status=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddPreMemoryEvent (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT8 Mode,=0D
+ IN UINT8 Status=0D
+ )=0D
+{=0D
+ VTDLOG_PEI_BUFFER_HOB *BufferHob;=0D
+ VOID *HobPtr;=0D
+ UINT8 Index;=0D
+=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ BufferHob =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ for (Index =3D 0; Index < VTD_LOG_PEI_PRE_MEM_BAR_MAX; Index++) {=0D
+ if (BufferHob->PreMemInfo[Index].Mode =3D=3D VTD_LOG_PEI_PRE_MEM_NOT=
_USED) {=0D
+ //=0D
+ // Found a free posttion=0D
+ //=0D
+ BufferHob->PreMemInfo[Index].BarAddress =3D (UINT32) VtdUnitBaseAd=
dress;=0D
+ BufferHob->PreMemInfo[Index].Mode =3D Mode;=0D
+ BufferHob->PreMemInfo[Index].Status =3D Status;=0D
+ break;=0D
+ }=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Initializes the VTd Log.=0D
+=0D
+ @param[in] MemoryInitialized TRUE: It is post-memory phase=0D
+ FALSE: It is pre-memory phase=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogInitialize(=0D
+ BOOLEAN MemoryInitialized=0D
+ )=0D
+{=0D
+ VTDLOG_PEI_BUFFER_HOB *BufferHob;=0D
+ VOID *HobPtr;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) > 0) {=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr =3D=3D NULL) {=0D
+ BufferHob =3D BuildGuidHob (&gVTdLogBufferHobGuid, sizeof (VTDLOG_PE=
I_BUFFER_HOB));=0D
+ ASSERT (BufferHob !=3D NULL);=0D
+=0D
+ ZeroMem (BufferHob, sizeof (VTDLOG_PEI_BUFFER_HOB));=0D
+ } else {=0D
+ BufferHob =3D GET_GUID_HOB_DATA (HobPtr);=0D
+ }=0D
+=0D
+ if (MemoryInitialized) {=0D
+ if ((BufferHob->PostMemBuffer =3D=3D 0) && (PcdGet32 (PcdVTdPeiPostM=
emLogBufferSize) > 0)) {=0D
+ BufferHob->PostMemBufferUsed =3D 0;=0D
+ BufferHob->PostMemBuffer =3D (UINTN) AllocateAlignedPages (EFI_SIZ=
E_TO_PAGES (PcdGet32 (PcdVTdPeiPostMemLogBufferSize)), sizeof (UINT8));=0D
+ }=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU PPI exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ @param[in] This The PPI instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA acces=
s request.=0D
+ @param[in] Mapping The mapping value returned from Map().=
=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory =
range specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was return=
ed by Map().=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combi=
nation of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not sup=
ported by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory =
range specified by Mapping.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availab=
le to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error whi=
le attempting the operation.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuSetAttribute (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN VOID *Mapping,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ //=0D
+ // check and clear VTd error=0D
+ //=0D
+ DumpVtdIfError ();=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuSetAttribute:\n"));=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuSetAttribute: DmaBufferCurrentTop =3D=3D =
0\n"));=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] Operation Indicates if the bus master is going t=
o read or write to system memory.=0D
+ @param [in] HostAddress The system memory address to map to th=
e PCI controller.=0D
+ @param [in] [out] NumberOfBytes On input the number of bytes to map. O=
n output the number of bytes=0D
+ that were mapped.=0D
+ @param [out] DeviceAddress The resulting map address for the bus =
master PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param [out] Mapping A resulting value to pass to Unmap().=
=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned =
NumberOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a =
common buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due=
to a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the =
requested address.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuMap (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %=
x\n", HostAddress, *NumberOfBytes));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+ DEBUG ((DEBUG_INFO, " Operation - %x\n", Operation));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64) {=0D
+ *DeviceAddress =3D (UINTN) HostAddress;=0D
+ *Mapping =3D NULL;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ Length =3D *NumberOfBytes + sizeof (MAP_INFO);=0D
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBuff=
erCurrentBottom) {=0D
+ DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));=0D
+ VTdLogAddEvent (VTDLOG_PEI_VTD_ERROR, VTD_LOG_PEI_VTD_ERROR_PPI_MAP, L=
ength);=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ *DeviceAddress =3D DmaBufferInfo->DmaBufferCurrentBottom;=0D
+ DmaBufferInfo->DmaBufferCurrentBottom +=3D Length;=0D
+=0D
+ MapInfo =3D (VOID *) (UINTN) (*DeviceAddress + *NumberOfBytes);=0D
+ MapInfo->Signature =3D MAP_INFO_SIGNATURE;=0D
+ MapInfo->Operation =3D Operation;=0D
+ MapInfo->NumberOfBytes =3D *NumberOfBytes;=0D
+ MapInfo->HostAddress =3D (UINTN) HostAddress;=0D
+ MapInfo->DeviceAddress =3D *DeviceAddress;=0D
+ *Mapping =3D MapInfo;=0D
+ DEBUG ((DEBUG_INFO, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Opera=
tion, (UINTN) *DeviceAddress, MapInfo));=0D
+=0D
+ //=0D
+ // If this is a read operation from the Bus Master's point of view,=0D
+ // then copy the contents of the real buffer into the mapped buffer=0D
+ // so the Bus Master can read the contents of the real buffer.=0D
+ //=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterRead ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterRead64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_PPI_MAP, (UINT64) HostAddress, Length);=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] Mapping The mapping value returned from Map().=
=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was return=
ed by Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the targ=
et system memory.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuUnmap (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN VOID *Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ MapInfo =3D Mapping;=0D
+ ASSERT (MapInfo->Signature =3D=3D MAP_INFO_SIGNATURE);=0D
+ DEBUG ((DEBUG_INFO, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n",=
MapInfo->Operation, (UINTN) MapInfo->DeviceAddress, MapInfo->NumberOfBytes=
));=0D
+=0D
+ //=0D
+ // If this is a write operation from the Bus Master's point of view,=0D
+ // then copy the contents of the mapped buffer into the real buffer=0D
+ // so the processor can read the contents of the real buffer.=0D
+ //=0D
+ if (MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite ||=0D
+ MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ Length =3D MapInfo->NumberOfBytes + sizeof (MAP_INFO);=0D
+ if (DmaBufferInfo->DmaBufferCurrentBottom =3D=3D MapInfo->DeviceAddress =
+ Length) {=0D
+ DmaBufferInfo->DmaBufferCurrentBottom -=3D Length;=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] MemoryType The type of memory to allocate, EfiBoo=
tServicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param [in] Pages The number of pages to allocate.=0D
+ @param [in] [out] HostAddress A pointer to store the base system mem=
ory address of the=0D
+ allocated range.=0D
+ @param [in] Attributes The requested bit mask of attributes f=
or the allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were alloca=
ted.=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only le=
gal attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED an=
d DUAL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocate=
d.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ )=0D
+{=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ Length =3D EFI_PAGES_TO_SIZE (Pages);=0D
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBuff=
erCurrentBottom) {=0D
+ DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));=0D
+ VTdLogAddEvent (VTDLOG_PEI_VTD_ERROR, VTD_LOG_PEI_VTD_ERROR_PPI_ALLOC,=
Length);=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ *HostAddress =3D (VOID *) (UINTN) (DmaBufferInfo->DmaBufferCurrentTop - =
Length);=0D
+ DmaBufferInfo->DmaBufferCurrentTop -=3D Length;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAdd=
ress));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_PPI_ALLOC_BUFFER, (UINT64) (*HostAddress), Le=
ngth);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] Pages The number of pages to free.=0D
+ @param [in] HostAddress The base system memory address of the =
allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=
=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddr=
ess and Pages=0D
+ was not allocated with AllocateBuffer(=
).=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ )=0D
+{=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA (Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", P=
ages, HostAddress));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ Length =3D EFI_PAGES_TO_SIZE (Pages);=0D
+ if ((UINTN)HostAddress =3D=3D DmaBufferInfo->DmaBufferCurrentTop) {=0D
+ DmaBufferInfo->DmaBufferCurrentTop +=3D Length;=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+EDKII_IOMMU_PPI mIoMmuPpi =3D {=0D
+ EDKII_IOMMU_PPI_REVISION,=0D
+ PeiIoMmuSetAttribute,=0D
+ PeiIoMmuMap,=0D
+ PeiIoMmuUnmap,=0D
+ PeiIoMmuAllocateBuffer,=0D
+ PeiIoMmuFreeBuffer,=0D
+};=0D
+=0D
+CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList =3D {=0D
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,=0D
+ &gEdkiiIoMmuPpiGuid,=0D
+ (VOID *) &mIoMmuPpi=0D
+};=0D
+=0D
+/**=0D
+ Get ACPI DMAT Table from EdkiiVTdInfo PPI=0D
+=0D
+ @retval Address ACPI DMAT Table address=0D
+ @retval NULL Failed to get ACPI DMAT Table=0D
+**/=0D
+EFI_ACPI_DMAR_HEADER * GetAcpiDmarTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+=0D
+ //=0D
+ // Get the DMAR table=0D
+ //=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEdkiiVTdInfoPpiGuid,=0D
+ 0,=0D
+ NULL,=0D
+ (VOID **)&AcpiDmarTable=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Fail to get ACPI DMAR Table : %r\n", Status));=0D
+ AcpiDmarTable =3D NULL;=0D
+ } else {=0D
+ VtdLibDumpAcpiDmarDrhd (NULL, NULL, AcpiDmarTable);=0D
+ }=0D
+=0D
+ return AcpiDmarTable;=0D
+}=0D
+=0D
+/**=0D
+ Get the VTd engine context information hob.=0D
+=0D
+ @retval The VTd engine context information.=0D
+=0D
+**/=0D
+VTD_INFO *=0D
+GetVTdInfoHob (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VOID *Hob;=0D
+ VTD_INFO *VTdInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mVTdInfoGuid);=0D
+ if (Hob =3D=3D NULL) {=0D
+ VTdInfo =3D BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO));=0D
+ if (VTdInfo !=3D NULL) {=0D
+ ZeroMem (VTdInfo, sizeof (VTD_INFO));=0D
+ }=0D
+ } else {=0D
+ VTdInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+ }=0D
+ return VTdInfo;=0D
+}=0D
+=0D
+/**=0D
+ Callback function of parse DMAR DRHD table in pre-memory phase.=0D
+=0D
+ @param [in] [out] Context Callback function context.=0D
+ @param [in] VTdIndex The VTd engine index.=0D
+ @param [in] DmarDrhd The DRHD table.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessDhrdPreMemory (=0D
+ IN OUT VOID *Context,=0D
+ IN UINTN VTdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, DmarD=
rhd->RegisterBaseAddress));=0D
+=0D
+ EnableVTdTranslationProtectionBlockDma ((UINTN) DmarDrhd->RegisterBaseAd=
dress);=0D
+}=0D
+=0D
+/**=0D
+ Callback function of parse DMAR DRHD table in post memory phase.=0D
+=0D
+ @param [in] [out] Context Callback function context.=0D
+ @param [in] VTdIndex The VTd engine index.=0D
+ @param [in] DmarDrhd The DRHD table.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessDrhdPostMemory (=0D
+ IN OUT VOID *Context,=0D
+ IN UINTN VTdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+ UINTN Index;=0D
+=0D
+ VtdUnitInfo =3D (VTD_UNIT_INFO *) Context;=0D
+=0D
+ if (DmarDrhd->RegisterBaseAddress =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO,"VTd Base Address is 0\n"));=0D
+ ASSERT (FALSE);=0D
+ return;=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < VTD_UNIT_MAX; Index++) {=0D
+ if (VtdUnitInfo[Index].VtdUnitBaseAddress =3D=3D DmarDrhd->RegisterBas=
eAddress) {=0D
+ DEBUG ((DEBUG_INFO,"Find VTD (%d) [0x%08x] Exist\n", VTdIndex, DmarD=
rhd->RegisterBaseAddress));=0D
+ return;=0D
+ }=0D
+ }=0D
+=0D
+ for (VTdIndex =3D 0; VTdIndex < VTD_UNIT_MAX; VTdIndex++) {=0D
+ if (VtdUnitInfo[VTdIndex].VtdUnitBaseAddress =3D=3D 0) {=0D
+ VtdUnitInfo[VTdIndex].VtdUnitBaseAddress =3D (UINTN) DmarDrhd->Regis=
terBaseAddress;=0D
+ VtdUnitInfo[VTdIndex].Segment =3D DmarDrhd->SegmentNumber;=0D
+ VtdUnitInfo[VTdIndex].Flags =3D DmarDrhd->Flags;=0D
+ VtdUnitInfo[VTdIndex].Done =3D FALSE;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, D=
marDrhd->RegisterBaseAddress));=0D
+ DEBUG ((DEBUG_INFO," Segment - %d, Flags - 0x%x\n", DmarDrhd->Seg=
mentNumber, DmarDrhd->Flags));=0D
+ return;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VtdUnitInfo Table is full\n"));=0D
+ ASSERT (FALSE);=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Initializes the Intel VTd Info in post memory phase.=0D
+=0D
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized=
.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.=0D
+**/=0D
+EFI_STATUS=0D
+InitVTdInfo (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VTD_INFO *VTdInfo;=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+ UINTN VtdUnitNumber;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ VTdInfo =3D GetVTdInfoHob ();=0D
+ ASSERT (VTdInfo !=3D NULL);=0D
+=0D
+ AcpiDmarTable =3D GetAcpiDmarTable ();=0D
+ ASSERT (AcpiDmarTable !=3D NULL);=0D
+=0D
+ if (VTdInfo->VtdUnitInfo =3D=3D NULL) {=0D
+ //=0D
+ // Genrate a new Vtd Unit Info Table=0D
+ //=0D
+ VTdInfo->VtdUnitInfo =3D AllocateZeroPages (EFI_SIZE_TO_PAGES (sizeof =
(VTD_UNIT_INFO) * VTD_UNIT_MAX));=0D
+ if (VTdInfo->VtdUnitInfo =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "InitVTdInfo - OUT_OF_RESOURCE\n"));=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+ VtdUnitInfo =3D VTdInfo->VtdUnitInfo;=0D
+=0D
+ if (VTdInfo->HostAddressWidth =3D=3D 0) {=0D
+ VTdInfo->HostAddressWidth =3D AcpiDmarTable->HostAddressWidth;=0D
+ }=0D
+=0D
+ if (VTdInfo->HostAddressWidth !=3D AcpiDmarTable->HostAddressWidth) {=0D
+ DEBUG ((DEBUG_ERROR, "Host Address Width is not match.\n"));=0D
+ ASSERT (FALSE);=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ //=0D
+ // Parse the DMAR ACPI Table to the new Vtd Unit Info Table=0D
+ //=0D
+ VtdUnitNumber =3D ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDrhdPost=
Memory, VtdUnitInfo);=0D
+ if (VtdUnitNumber =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ for (VTdInfo->VTdEngineCount =3D 0; VTdInfo->VTdEngineCount < VTD_UNIT_M=
AX; VTdInfo->VTdEngineCount++) {=0D
+ if (VtdUnitInfo[VTdInfo->VTdEngineCount].VtdUnitBaseAddress =3D=3D 0) =
{=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ VTdInfo->AcpiDmarTable =3D AcpiDmarTable;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Initializes the Intel VTd DMAR for block all DMA.=0D
+=0D
+ @retval EFI_SUCCESS Driver is successfully initialized.=0D
+ @retval RETURN_NOT_READY Fail to get VTdInfo Hob .=0D
+**/=0D
+EFI_STATUS=0D
+InitVTdDmarBlockAll (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+=0D
+ //=0D
+ // Get the DMAR table=0D
+ //=0D
+ AcpiDmarTable =3D GetAcpiDmarTable ();=0D
+ ASSERT (AcpiDmarTable !=3D NULL);=0D
+=0D
+ //=0D
+ // Parse the DMAR table and block all DMA=0D
+ //=0D
+ return ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDhrdPreMemory, NULL=
);=0D
+}=0D
+=0D
+/**=0D
+ Initializes DMA buffer=0D
+=0D
+ @retval EFI_SUCCESS DMA buffer is successfully initialized.=0D
+ @retval EFI_INVALID_PARAMETER Invalid DMA buffer size.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize DMA buffer.=0D
+**/=0D
+EFI_STATUS=0D
+InitDmaBuffer(=0D
+ VOID=0D
+ )=0D
+{=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+ VOID *Hob;=0D
+ VOID *VtdPmrHobPtr;=0D
+ VTD_PMR_INFO_HOB *VtdPmrHob;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "InitDmaBuffer :\n"));=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ ASSERT(Hob !=3D NULL);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA (Hob);=0D
+=0D
+ /**=0D
+ When gVtdPmrInfoDataHobGuid exists, it means:=0D
+ 1. Dma buffer is reserved by memory initialize code=0D
+ 2. PeiGetVtdPmrAlignmentLib is used to get alignment=0D
+ 3. Protection regions are determined by the system memory map=0D
+ 4. Protection regions will be conveyed through VTD_PMR_INFO_HOB=0D
+=0D
+ When gVtdPmrInfoDataHobGuid dosen't exist, it means:=0D
+ 1. IntelVTdDmarPei driver will calcuate the protected memory alignment=
=0D
+ 2. Dma buffer is reserved by AllocateAlignedPages()=0D
+ **/=0D
+=0D
+=0D
+ if (DmaBufferInfo->DmaBufferSize =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferSize is 0\n"));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ if (DmaBufferInfo->DmaBufferBase =3D=3D 0) {=0D
+ VtdPmrHobPtr =3D GetFirstGuidHob (&gVtdPmrInfoDataHobGuid);=0D
+ if (VtdPmrHobPtr !=3D NULL) {=0D
+ //=0D
+ // Get the protected memory ranges information from the VTd PMR hob=
=0D
+ //=0D
+ VtdPmrHob =3D GET_GUID_HOB_DATA (VtdPmrHobPtr);=0D
+=0D
+ if ((VtdPmrHob->ProtectedHighBase - VtdPmrHob->ProtectedLowLimit) < =
DmaBufferInfo->DmaBufferSize) {=0D
+ DEBUG ((DEBUG_ERROR, " DmaBufferSize not enough\n"));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ DmaBufferInfo->DmaBufferBase =3D VtdPmrHob->ProtectedLowLimit;=0D
+ } else {=0D
+ //=0D
+ // Allocate memory for DMA buffer=0D
+ //=0D
+ DmaBufferInfo->DmaBufferBase =3D (UINTN) AllocateAlignedPages (EFI_S=
IZE_TO_PAGES (DmaBufferInfo->DmaBufferSize), 0);=0D
+ if (DmaBufferInfo->DmaBufferBase =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n"));=0D
+ }=0D
+=0D
+ DmaBufferInfo->DmaBufferCurrentTop =3D DmaBufferInfo->DmaBufferBase + =
DmaBufferInfo->DmaBufferSize;=0D
+ DmaBufferInfo->DmaBufferCurrentBottom =3D DmaBufferInfo->DmaBufferBase=
;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo-=
+=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%x\n", DmaBufferInfo->D=
maBufferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%x\n", DmaBufferInfo->D=
maBufferCurrentBottom));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_PROTECT_MEMORY_RANGE, DmaBufferInfo->DmaBuffe=
rCurrentBottom, DmaBufferInfo->DmaBufferCurrentTop);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Initializes the Intel VTd DMAR for DMA buffer.=0D
+=0D
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized=
.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+InitVTdDmarForDma (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VTD_INFO *VTdInfo;=0D
+=0D
+ EFI_STATUS Status;=0D
+ EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;=0D
+ EDKII_IOMMU_PPI *OldIoMmuPpi;=0D
+=0D
+ VTdInfo =3D GetVTdInfoHob ();=0D
+ ASSERT (VTdInfo !=3D NULL);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));=0D
+ Status =3D PrepareVtdConfig (VTdInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ return Status;=0D
+ }=0D
+=0D
+ // create root entry table=0D
+ DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));=0D
+ Status =3D SetupTranslationTable (VTdInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));=0D
+ Status =3D EnableVTdTranslationProtection(VTdInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Install gEdkiiIoMmuPpiGuid\n"));=0D
+ // install protocol=0D
+ //=0D
+ // (Re)Install PPI.=0D
+ //=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEdkiiIoMmuPpiGuid,=0D
+ 0,=0D
+ &OldDescriptor,=0D
+ (VOID **) &OldIoMmuPpi=0D
+ );=0D
+ if (!EFI_ERROR (Status)) {=0D
+ Status =3D PeiServicesReInstallPpi (OldDescriptor, &mIoMmuPpiList);=0D
+ } else {=0D
+ Status =3D PeiServicesInstallPpi (&mIoMmuPpiList);=0D
+ }=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ This function handles S3 resume task at the end of PEI=0D
+=0D
+ @param[in] PeiServices Pointer to PEI Services Table.=0D
+ @param[in] NotifyDesc Pointer to the descriptor for the Notifica=
tion event that=0D
+ caused this function to execute.=0D
+ @param[in] Ppi Pointer to the PPI data associated with th=
is function.=0D
+=0D
+ @retval EFI_STATUS Always return EFI_SUCCESS=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+S3EndOfPeiNotify(=0D
+ IN EFI_PEI_SERVICES **PeiServices,=0D
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,=0D
+ IN VOID *Ppi=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, "VTd DMAR PEI S3EndOfPeiNotify\n"));=0D
+=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) {=0D
+ DumpVtdIfError ();=0D
+=0D
+ DisableVTdTranslationProtection (GetVTdInfoHob ());=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc =3D {=0D
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA=
TE_LIST),=0D
+ &gEfiEndOfPeiSignalPpiGuid,=0D
+ S3EndOfPeiNotify=0D
+};=0D
+=0D
+/**=0D
+ This function handles VTd engine setup=0D
+=0D
+ @param[in] PeiServices Pointer to PEI Services Table.=0D
+ @param[in] NotifyDesc Pointer to the descriptor for the Notifica=
tion event that=0D
+ caused this function to execute.=0D
+ @param[in] Ppi Pointer to the PPI data associated with th=
is function.=0D
+=0D
+ @retval EFI_STATUS Always return EFI_SUCCESS=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+VTdInfoNotify (=0D
+ IN EFI_PEI_SERVICES **PeiServices,=0D
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,=0D
+ IN VOID *Ppi=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VOID *MemoryDiscovered;=0D
+ BOOLEAN MemoryInitialized;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));=0D
+=0D
+ //=0D
+ // Check if memory is initialized.=0D
+ //=0D
+ MemoryInitialized =3D FALSE;=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEfiPeiMemoryDiscoveredPpiGuid,=0D
+ 0,=0D
+ NULL,=0D
+ &MemoryDiscovered=0D
+ );=0D
+ if (!EFI_ERROR(Status)) {=0D
+ MemoryInitialized =3D TRUE;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));=0D
+=0D
+ if (!MemoryInitialized) {=0D
+ //=0D
+ // If the memory is not initialized,=0D
+ // Protect all system memory=0D
+ //=0D
+=0D
+ InitVTdDmarBlockAll ();=0D
+=0D
+ //=0D
+ // Install PPI.=0D
+ //=0D
+ Status =3D PeiServicesInstallPpi (&mIoMmuPpiList);=0D
+ ASSERT_EFI_ERROR(Status);=0D
+ } else {=0D
+ //=0D
+ // If the memory is initialized,=0D
+ // Allocate DMA buffer and protect rest system memory=0D
+ //=0D
+=0D
+ VTdLogInitialize (TRUE);=0D
+=0D
+ Status =3D InitDmaBuffer ();=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // NOTE: We need reinit VTdInfo because previous information might be =
overriden.=0D
+ //=0D
+ Status =3D InitVTdInfo ();=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D InitVTdDmarForDma ();=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc =3D {=0D
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA=
TE_LIST),=0D
+ &gEdkiiVTdInfoPpiGuid,=0D
+ VTdInfoNotify=0D
+};=0D
+=0D
+/**=0D
+ Initializes the Intel VTd DMAR PEIM.=0D
+=0D
+ @param[in] FileHandle Handle of the file being invoked.=0D
+ @param[in] PeiServices Describes the list of possible PEI Service=
s.=0D
+=0D
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized=
.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IntelVTdDmarInitialize (=0D
+ IN EFI_PEI_FILE_HANDLE FileHandle,=0D
+ IN CONST EFI_PEI_SERVICES **PeiServices=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_BOOT_MODE BootMode;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "IntelVTdDmarInitialize\n"));=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VTdLogInitialize (FALSE);=0D
+=0D
+ DmaBufferInfo =3D BuildGuidHob (&mDmaBufferInfoGuid, sizeof (DMA_BUFFER_=
INFO));=0D
+ ASSERT(DmaBufferInfo !=3D NULL);=0D
+ if (DmaBufferInfo =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ ZeroMem (DmaBufferInfo, sizeof (DMA_BUFFER_INFO));=0D
+=0D
+ PeiServicesGetBootMode (&BootMode);=0D
+=0D
+ if (BootMode =3D=3D BOOT_ON_S3_RESUME) {=0D
+ DmaBufferInfo->DmaBufferSize =3D PcdGet32 (PcdVTdPeiDmaBufferSizeS3);=
=0D
+ } else {=0D
+ DmaBufferInfo->DmaBufferSize =3D PcdGet32 (PcdVTdPeiDmaBufferSize);=0D
+ }=0D
+=0D
+ Status =3D PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Register EndOfPei Notify for S3=0D
+ //=0D
+ if (BootMode =3D=3D BOOT_ON_S3_RESUME) {=0D
+ Status =3D PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/I=
ntelVTdCorePei.h
new file mode 100644
index 000000000..1ddf8fbf7
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.h
@@ -0,0 +1,272 @@
+/** @file=0D
+ The definition for DMA access Library.=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef __DMA_ACCESS_LIB_H__=0D
+#define __DMA_ACCESS_LIB_H__=0D
+=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+//=0D
+// Use 256-bit descriptor=0D
+// Queue size is 128.=0D
+//=0D
+#define VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH 1=0D
+#define VTD_INVALIDATION_QUEUE_SIZE 0=0D
+=0D
+typedef struct {=0D
+ BOOLEAN Done;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Segment;=0D
+ UINT8 Flags;=0D
+ VTD_VER_REG VerReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ BOOLEAN Is5LevelPaging;=0D
+ UINT8 EnableQueuedInvalidation;=0D
+ VOID *QiDescBuffer;=0D
+ UINTN QiDescBufferSize;=0D
+ UINTN FixedSecondLevelPagingEntry;=0D
+ UINTN RootEntryTable;=0D
+ UINTN ExtRootEntryTable;=0D
+ UINTN RootEntryTablePageSize;=0D
+ UINTN ExtRootEntryTablePageSize;=0D
+} VTD_UNIT_INFO;=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+ UINT8 HostAddressWidth;=0D
+ VTD_REGESTER_THIN_INFO *RegsInfoBuffer;=0D
+ UINTN VTdEngineCount;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+} VTD_INFO;=0D
+=0D
+typedef struct {=0D
+ UINTN DmaBufferBase;=0D
+ UINTN DmaBufferSize;=0D
+ UINTN DmaBufferCurrentTop;=0D
+ UINTN DmaBufferCurrentBottom;=0D
+} DMA_BUFFER_INFO;=0D
+=0D
+typedef=0D
+VOID=0D
+(*PROCESS_DRHD_CALLBACK_FUNC) (=0D
+ IN OUT VOID *Context,=0D
+ IN UINTN VTdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ );=0D
+=0D
+/**=0D
+ Enable VTd translation table protection for block DMA=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtectionBlockDma (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Enable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Disable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+**/=0D
+VOID=0D
+DisableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @param[in] AcpiDmarTable DMAR ACPI table=0D
+ @param[in] Callback Callback function for handle DRHD=0D
+ @param[in] Context Callback function Context=0D
+=0D
+ @return the VTd engine number.=0D
+=0D
+**/=0D
+UINTN=0D
+ParseDmarAcpiTableDrhd (=0D
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,=0D
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,=0D
+ IN VOID *Context=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+DumpAcpiDMAR (=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ );=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Prepare Vtd config success=0D
+**/=0D
+EFI_STATUS=0D
+PrepareVtdConfig (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ );=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Get the VTd engine context information hob.=0D
+=0D
+ @retval The VTd engine context information.=0D
+=0D
+**/=0D
+VTD_INFO *=0D
+GetVTdInfoHob (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Add the VTd log event in post memory phase.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ );=0D
+=0D
+/**=0D
+ Add the VTd log event in pre-memory phase.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Mode Pre-memory DMA protection mode.=0D
+ @param[in] Status Status=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddPreMemoryEvent (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT8 Mode,=0D
+ IN UINT8 Status=0D
+ );=0D
+=0D
+extern EFI_GUID mVTdInfoGuid;=0D
+extern EFI_GUID mDmaBufferInfoGuid;=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei=
/IntelVTdCorePei.inf
new file mode 100644
index 000000000..f756c543c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.inf
@@ -0,0 +1,70 @@
+## @file=0D
+# Component INF file for the Intel VTd DMAR PEIM.=0D
+#=0D
+# This driver initializes VTd engine based upon EDKII_VTD_INFO_PPI=0D
+# and provide DMA protection in PEI.=0D
+#=0D
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010017=0D
+ BASE_NAME =3D IntelVTdCorePei=0D
+ MODULE_UNI_FILE =3D IntelVTdCorePei.uni=0D
+ FILE_GUID =3D 9311b0cc-5c08-4c0a-bec8-23afab024e48=0D
+ MODULE_TYPE =3D PEIM=0D
+ VERSION_STRING =3D 2.0=0D
+ ENTRY_POINT =3D IntelVTdDmarInitialize=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[Sources]=0D
+ IntelVTdCorePei.c=0D
+ IntelVTdCorePei.h=0D
+ IntelVTdDmar.c=0D
+ DmarTable.c=0D
+ TranslationTable.c=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ BaseMemoryLib=0D
+ BaseLib=0D
+ PeimEntryPoint=0D
+ PeiServicesLib=0D
+ HobLib=0D
+ IoLib=0D
+ CacheMaintenanceLib=0D
+ PciSegmentLib=0D
+ IntelVTdPeiDxeLib=0D
+=0D
+[Guids]=0D
+ gVTdLogBufferHobGuid ## PRODUCES CONSUMES=0D
+ gVtdPmrInfoDataHobGuid ## CONSUMES=0D
+=0D
+[Ppis]=0D
+ gEdkiiIoMmuPpiGuid ## PRODUCES=0D
+ gEdkiiVTdInfoPpiGuid ## CONSUMES=0D
+ gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES=0D
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES=0D
+ gEdkiiVTdNullRootEntryTableGuid ## CONSUMES=0D
+=0D
+[Pcd]=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSize ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3 ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize ## CONSUME=
S=0D
+=0D
+[Depex]=0D
+ gEfiPeiMasterBootModePpiGuid AND=0D
+ gEdkiiVTdInfoPpiGuid=0D
+=0D
+[UserExtensions.TianoCore."ExtraFiles"]=0D
+ IntelVTdCorePeiExtra.uni=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei=
/IntelVTdCorePei.uni
new file mode 100644
index 000000000..2b5b260f5
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDmarPei Module Localized Abstract and Description Content=0D
+//=0D
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Intel VTd CORE PE=
I Driver."=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "This driver initi=
alizes VTd engine based upon EDKII_VTD_INFO_PPI and provide DMA protection =
to device in PEI."=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePeiExtra.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCo=
rePei/IntelVTdCorePeiExtra.uni
new file mode 100644
index 000000000..14848f924
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePeiExtra.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDmarPei Localized Strings and Content=0D
+//=0D
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+#string STR_PROPERTIES_MODULE_NAME=0D
+#language en-US=0D
+"Intel VTd CORE PEI Driver"=0D
+=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdDmar.c
new file mode 100644
index 000000000..d3876416c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdDma=
r.c
@@ -0,0 +1,727 @@
+/** @file=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/PeiServicesLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Ppi/VtdNullRootEntryTable.h>=0D
+#include <Ppi/IoMmu.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+#define VTD_CAP_REG_NFR_MAX (256)=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ if (VtdUnitInfo->ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *) Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_IQA_REG IqaReg;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ if (VtdUnitInfo->VerReg.Bits.Major <=3D 5) {=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for eng=
ine [0x%x]\n", VtdUnitBaseAddress));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);=0D
+ if (ECapReg.Bits.QI =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations i=
nterface for engine [0x%x]\n", VtdUnitBaseAddress));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 1;=0D
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]=
\n", VtdUnitBaseAddress));=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ if ((Reg32 & B_GSTS_REG_QIES) !=3D 0) {=0D
+ DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n"));=0D
+=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitBaseAddress);=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the Invalidation Queue Tail Register to zero.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);=0D
+=0D
+ //=0D
+ // Setup the IQ address, size and descriptor width through the Invalidat=
ion Queue Address Register=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ VtdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <=
< (VTD_INVALIDATION_QUEUE_SIZE + 7)));=0D
+ VtdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VtdUni=
tInfo->QiDescBufferSize));=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"))=
;=0D
+ VTdLogAddEvent (VTDLOG_PEI_QUEUED_INVALIDATION, VTD_LOG_QI_ERROR_OUT=
_OF_RESOURCES, VtdUnitBaseAddress);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VtdUnitInfo=
->QiDescBufferSize));=0D
+ //=0D
+ // 4KB Aligned address=0D
+ //=0D
+ IqaReg.Uint64 =3D (UINT64) (UINTN) VtdUnitInfo->QiDescBuffer;=0D
+ IqaReg.Bits.DW =3D VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH;=0D
+ IqaReg.Bits.QS =3D VTD_INVALIDATION_QUEUE_SIZE;=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ DEBUG ((DEBUG_INFO, "IQA_REG =3D 0x%lx, IQH_REG =3D 0x%lx\n", IqaReg.Uin=
t64, MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));=0D
+=0D
+ //=0D
+ // Enable the queued invalidation interface through the Global Command R=
egister.=0D
+ // When enabled, hardware sets the QIES field in the Global Status Regis=
ter.=0D
+ //=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 |=3D B_GMCD_REG_QIE;=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG =3D =
0x%x\n", Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_QUEUED_INVALIDATION, VTD_LOG_QI_ENABLE, VtdUn=
itBaseAddress);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+SubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN QI_256_DESC *Desc=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_REGESTER_QI_INFO RegisterQi;=0D
+=0D
+ Status =3D VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress,=
Desc, FALSE);=0D
+ if (Status =3D=3D EFI_DEVICE_ERROR) {=0D
+ RegisterQi.BaseAddress =3D VtdUnitBaseAddress;=0D
+ RegisterQi.FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG=
);;=0D
+ RegisterQi.IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_R=
EG);=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_QI, &Register=
Qi, sizeof (VTD_REGESTER_QI_INFO));=0D
+=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, RegisterQi.FstsReg & (B_=
FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE));=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);=0D
+ if ((Reg64 & B_CCMD_REG_ICC) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC i=
s set for VTD(%x)\n", VtdUnitInfo->VtdUnitBaseAddress));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));=0D
+ Reg64 |=3D (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);=0D
+ MmioWrite64 (VtdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);=
=0D
+ } while ((Reg64 & B_CCMD_REG_ICC) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC=
_GRAN(1) | QI_CC_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(VtdUnitInfo->VtdUnitBaseAddr=
ess, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_ECA=
P_REG);=0D
+=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.=
IRO * 16) + R_IOTLB_REG);=0D
+ if ((Reg64 & B_IOTLB_REG_IVT) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is se=
t for VTD(%x)\n", VtdUnitInfo->VtdUnitBaseAddress));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));=0D
+ Reg64 |=3D (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);=0D
+ MmioWrite64 (VtdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16)=
+ R_IOTLB_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bit=
s.IRO * 16) + R_IOTLB_REG);=0D
+ } while ((Reg64 & B_IOTLB_REG_IVT) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_CAP_=
REG);=0D
+ QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapR=
eg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1=
) | QI_IOTLB_TYPE;=0D
+ QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0=
);=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(VtdUnitInfo->VtdUnitBaseAddr=
ess, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation in pre-mem phase.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] RtaddrRegValue The value of RTADDR_REG.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmarPreMem (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT64 RtaddrRegValue=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+=0D
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUn=
itBaseAddress));=0D
+=0D
+ DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue));=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, RtaddrRegValue);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmarPreMem: waiting for RTPS bit to be set...=
\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP)=
;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG =3D 0x%x \n", Reg32));=
=0D
+=0D
+ //=0D
+ // Write Buffer Flush=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);=
=0D
+=0D
+ DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] RootEntryTable The address of the VTd RootEntryTable.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINTN RootEntryTable=0D
+ )=0D
+{=0D
+ UINTN VtdUnitBaseAddress;=0D
+ BOOLEAN TEWasEnabled;=0D
+=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBase=
Address));=0D
+=0D
+ //=0D
+ // Check TE was enabled or not.=0D
+ //=0D
+ TEWasEnabled =3D ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GSTS=
_REG_TE) =3D=3D B_GSTS_REG_TE);=0D
+=0D
+ if (TEWasEnabled && (VtdUnitInfo->ECapReg.Bits.ADMS =3D=3D 1) && PcdGetB=
ool (PcdVTdSupportAbortDmaMode)) {=0D
+ //=0D
+ // For implementations reporting Enhanced SRTP Support (ESRTPS) field =
as=0D
+ // Clear in the Capability register, software must not modify this fie=
ld while=0D
+ // DMA remapping is active (TES=3D1 in Global Status register).=0D
+ //=0D
+ if (VtdUnitInfo->CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG=
_TE);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable ADM=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (RootEntryTab=
le | V_RTADDR_REG_TTM_ADM));=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"=
));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRT=
P);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Enable Abort DMA Mode...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ } else {=0D
+ DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTabl=
e);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"=
));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRT=
P);=0D
+ }=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ InvalidateContextCache (VtdUnitInfo);=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ InvalidateIOTLB (VtdUnitInfo);=0D
+=0D
+ if (TEWasEnabled && (VtdUnitInfo->ECapReg.Bits.ADMS =3D=3D 1) && PcdGetB=
ool (PcdVTdSupportAbortDmaMode)) {=0D
+ if (VtdUnitInfo->CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG=
_TE);=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTabl=
e);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"=
));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRT=
P);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);=
=0D
+=0D
+ DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Enable VTd translation table protection for block DMA=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtectionBlockDma (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI *RootEntryTable;=0D
+ UINT8 Mode;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n",=
VtdUnitBaseAddress));=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", PcdGetBool (PcdV=
TdSupportAbortDmaMode)));=0D
+=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);=0D
+ DEBUG ((DEBUG_INFO, "ECapReg.ADMS : %d\n", ECapReg.Bits.ADMS));=0D
+=0D
+ if ((ECapReg.Bits.ADMS =3D=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMod=
e)) {=0D
+ Mode =3D VTD_LOG_PEI_PRE_MEM_ADM;=0D
+ //=0D
+ // Use Abort DMA Mode=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "Enable abort DMA mode.\n"));=0D
+ Status =3D EnableDmarPreMem (VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM)=
;=0D
+ } else {=0D
+ //=0D
+ // Use Null Root Entry Table=0D
+ //=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEdkiiVTdNullRootEntryTableGuid,=0D
+ 0,=0D
+ NULL,=0D
+ (VOID **)&RootEntryTable=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ Mode =3D VTD_LOG_PEI_PRE_MEM_DISABLE;=0D
+ DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n=
", Status));=0D
+ ASSERT (FALSE);=0D
+ } else {=0D
+ Mode =3D VTD_LOG_PEI_PRE_MEM_TE;=0D
+ DEBUG ((DEBUG_INFO, "Block All DMA by TE.\n"));=0D
+ Status =3D EnableDmarPreMem (VtdUnitBaseAddress, (UINT64) (*RootEntr=
yTable));=0D
+ }=0D
+ }=0D
+=0D
+ VTdLogAddPreMemoryEvent (VtdUnitBaseAddress, Mode, EFI_ERROR (Status) ? =
0 : 1);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Enable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+ if (VtdUnitInfo->Done) {=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index));=0D
+ continue;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ExtRootEntryTable !=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", I=
ndex, VtdUnitInfo->ExtRootEntryTable));=0D
+ Status =3D EnableDmar (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable |=
BIT11);=0D
+ } else {=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", Inde=
x, VtdUnitInfo->RootEntryTable));=0D
+ Status =3D EnableDmar (VtdUnitInfo, VtdUnitInfo->RootEntryTable);=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_POST_MEM_ENABLE_DMA_PROTECT, VTdInfo->VtdUn=
itInfo[Index].VtdUnitBaseAddress, Status);=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", Index));=0D
+ return Status;=0D
+ }=0D
+ VtdUnitInfo->Done =3D TRUE;=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+**/=0D
+VOID=0D
+DisableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ if (VTdInfo =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - %d Vtd Engine\n",=
VTdInfo->VTdEngineCount));=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+=0D
+ VtdLibDisableDmar (VtdUnitInfo->VtdUnitBaseAddress);=0D
+ VTdLogAddEvent (VTDLOG_PEI_POST_MEM_DISABLE_DMA_PROTECT, VtdUnitInfo->=
VtdUnitBaseAddress, 0);=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation !=3D 0) {=0D
+ //=0D
+ // Disable queued invalidation interface.=0D
+ //=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitInfo->VtdUnitBaseAd=
dress);=0D
+=0D
+ if (VtdUnitInfo->QiDescBuffer !=3D NULL) {=0D
+ FreePages(VtdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VtdUnitInf=
o->QiDescBufferSize));=0D
+ VtdUnitInfo->QiDescBuffer =3D NULL;=0D
+ VtdUnitInfo->QiDescBufferSize =3D 0;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ VTdLogAddEvent (VTDLOG_PEI_QUEUED_INVALIDATION, VTD_LOG_QI_DISABLE, =
VtdUnitInfo->VtdUnitBaseAddress);=0D
+ }=0D
+ }=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Check if VTd engine use 5 level paging.=0D
+=0D
+ @param[in] HostAddressWidth Host Address Width.=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[out] Is5LevelPaging Use 5 level paging or not=0D
+=0D
+ @retval EFI_SUCCESS Success=0D
+ @retval EFI_UNSUPPORTED Feature is not support=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VtdCheckUsing5LevelPaging (=0D
+ IN UINT8 HostAddressWidth,=0D
+ IN VTD_CAP_REG CapReg,=0D
+ OUT BOOLEAN *Is5LevelPaging=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, " CapReg SAGAW bits : 0x%02x\n", CapReg.Bits.SAGAW)=
);=0D
+=0D
+ *Is5LevelPaging =3D FALSE;=0D
+ if ((CapReg.Bits.SAGAW & BIT3) !=3D 0) {=0D
+ *Is5LevelPaging =3D TRUE;=0D
+ if ((HostAddressWidth <=3D 48) &&=0D
+ ((CapReg.Bits.SAGAW & BIT2) !=3D 0)) {=0D
+ *Is5LevelPaging =3D FALSE;=0D
+ } else {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ }=0D
+ if ((CapReg.Bits.SAGAW & (BIT3 | BIT2)) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, " Using %d Level Paging\n", *Is5LevelPaging ? 5 : 4=
));=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Prepare Vtd config success=0D
+**/=0D
+EFI_STATUS=0D
+PrepareVtdConfig (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ if (VTdInfo->RegsInfoBuffer =3D=3D NULL) {=0D
+ VTdInfo->RegsInfoBuffer =3D AllocateZeroPages (EFI_SIZE_TO_PAGES (size=
of (VTD_REGESTER_THIN_INFO) + sizeof (VTD_UINT128) * VTD_CAP_REG_NFR_MAX));=
=0D
+ ASSERT (VTdInfo->RegsInfoBuffer !=3D NULL);=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+ if (VtdUnitInfo->Done) {=0D
+ continue;=0D
+ }=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+ DEBUG ((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitBaseAddress));=0D
+=0D
+ VtdUnitInfo->VerReg.Uint32 =3D MmioRead32 (VtdUnitBaseAddress + R_VER_=
REG);=0D
+ VtdUnitInfo->CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_=
REG);=0D
+ VtdUnitInfo->ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECA=
P_REG);=0D
+ DEBUG ((DEBUG_INFO, " VER_REG : 0x%08X\n", VtdUnitInfo->VerReg.Uint3=
2));=0D
+ DEBUG ((DEBUG_INFO, " CAP_REG : 0x%016lX\n", VtdUnitInfo->CapReg.Uin=
t64));=0D
+ DEBUG ((DEBUG_INFO, " ECAP_REG : 0x%016lX\n", VtdUnitInfo->ECapReg.Ui=
nt64));=0D
+=0D
+ Status =3D VtdCheckUsing5LevelPaging (VTdInfo->HostAddressWidth, VtdUn=
itInfo->CapReg, &(VtdUnitInfo->Is5LevelPaging));=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported!!!!=
\n", VtdUnitInfo->CapReg.Bits.SAGAW));=0D
+ return Status;=0D
+ }=0D
+=0D
+ Status =3D PerpareCacheInvalidationInterface(&VTdInfo->VtdUnitInfo[Ind=
ex]);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VTD_INFO *VTdInfo;=0D
+ UINTN Num;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Index;=0D
+ VTD_REGESTER_THIN_INFO *VtdRegInfo;=0D
+ VTD_FRCD_REG FrcdReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ UINT32 FstsReg32;=0D
+ UINT32 FectlReg32;=0D
+ BOOLEAN HasError;=0D
+=0D
+ VTdInfo =3D GetVTdInfoHob ();=0D
+ if (VTdInfo =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VtdRegInfo =3D VTdInfo->RegsInfoBuffer;=0D
+ if (VtdRegInfo =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ for (Num =3D 0; Num < VTdInfo->VTdEngineCount; Num++) {=0D
+ HasError =3D FALSE;=0D
+ VtdUnitBaseAddress =3D VTdInfo->VtdUnitInfo[Num].VtdUnitBaseAddress;=0D
+ FstsReg32 =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG);=0D
+ if (FstsReg32 !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+ FectlReg32 =3D MmioRead32 (VtdUnitBaseAddress + R_FECTL_REG);=0D
+ if ((FectlReg32 & BIT30) !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+ for (Index =3D 0; Index < (UINT16) CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[0] =3D MmioRead64 (VtdUnitBaseAddress + ((CapReg.Bits=
.FRO * 16) + (Index * 16) + R_FRCD_REG));=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (VtdUnitBaseAddress + ((CapReg.Bits=
.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ if (HasError) {=0D
+ DEBUG ((DEBUG_INFO, "\n#### ERROR ####\n"));=0D
+=0D
+ VtdRegInfo->BaseAddress =3D VtdUnitBaseAddress;=0D
+ VtdRegInfo->GstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_=
REG);=0D
+ VtdRegInfo->RtaddrReg =3D MmioRead64 (VtdUnitBaseAddress + R_RTADD=
R_REG);;=0D
+ VtdRegInfo->FstsReg =3D FstsReg32;=0D
+ VtdRegInfo->FectlReg =3D FectlReg32;=0D
+ VtdRegInfo->IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERC=
D_REG);=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+ for (Index =3D 0; Index < (UINT16) CapReg.Bits.NFR + 1; Index++) {=0D
+ VtdRegInfo->FrcdReg[Index].Uint64Lo =3D MmioRead64 (VtdUnitBaseAdd=
ress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));=0D
+ VtdRegInfo->FrcdReg[Index].Uint64Hi =3D MmioRead64 (VtdUnitBaseAdd=
ress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)=
));=0D
+ }=0D
+ VtdRegInfo->FrcdRegNum =3D Index;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "\n#### ERROR ####\n"));=0D
+=0D
+ VtdLibDumpVtdRegsThin (NULL, NULL, VtdRegInfo);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "#### ERROR ####\n\n"));=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_THIN, VtdRe=
gInfo, sizeof (VTD_REGESTER_THIN_INFO) + sizeof (VTD_UINT128) * (VtdRegInfo=
->FrcdRegNum - 1));=0D
+=0D
+ //=0D
+ // Clear=0D
+ //=0D
+ for (Index =3D 0; Index < (UINT16) CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (VtdUnitBaseAddress + ((CapReg.Bi=
ts.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ //=0D
+ // Software writes the value read from this field (F) to Clear i=
t.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Ind=
ex * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.Uint64[1]);=0D
+ }=0D
+ }=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, MmioRead32 (VtdUnitBas=
eAddress + R_FSTS_REG));=0D
+ }=0D
+ }=0D
+}
\ No newline at end of file
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Tran=
slationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/=
TranslationTable.c
new file mode 100644
index 000000000..03a4544a0
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Translation=
Table.c
@@ -0,0 +1,926 @@
+/** @file=0D
+=0D
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/PeiServicesLib.h>=0D
+#include <Library/HobLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <Ppi/IoMmu.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Ppi/MemoryDiscovered.h>=0D
+#include <Ppi/EndOfPeiPhase.h>=0D
+#include <Guid/VtdPmrInfoHob.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (=
~((Alignment) - 1)))=0D
+#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))=
=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ )=0D
+{=0D
+ VOID *Addr;=0D
+=0D
+ Addr =3D AllocatePages (Pages);=0D
+ if (Addr =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ ZeroMem (Addr, EFI_PAGES_TO_SIZE (Pages));=0D
+ return Addr;=0D
+}=0D
+=0D
+/**=0D
+ Set second level paging entry attribute based upon IoMmuAccess.=0D
+=0D
+ @param[in] PtEntry The paging entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+**/=0D
+VOID=0D
+SetSecondLevelPagingEntryAttribute (=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PtEntry,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ PtEntry->Bits.Read =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_READ) !=3D 0)=
;=0D
+ PtEntry->Bits.Write =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_WRITE) !=3D 0=
);=0D
+ DEBUG ((DEBUG_VERBOSE, "SetSecondLevelPagingEntryAttribute - 0x%x - 0x%x=
\n", PtEntry, IoMmuAccess));=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry table.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] MemoryBase The base of the memory.=0D
+ @param[in] MemoryLimit The limit of the memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntryTable (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 MemoryBase,=0D
+ IN UINT64 MemoryLimit,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Lvl5Start;=0D
+ UINTN Lvl5End;=0D
+ UINTN Lvl4PagesStart;=0D
+ UINTN Lvl4PagesEnd;=0D
+ UINTN Lvl4Start;=0D
+ UINTN Lvl4End;=0D
+ UINTN Lvl3Start;=0D
+ UINTN Lvl3End;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 EndAddress;=0D
+ BOOLEAN Is5LevelPaging;=0D
+=0D
+ if (MemoryLimit =3D=3D 0) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ Lvl4PagesStart =3D 0;=0D
+ Lvl4PagesEnd =3D 0;=0D
+ Lvl4PtEntry =3D NULL;=0D
+ Lvl5PtEntry =3D NULL;=0D
+=0D
+ BaseAddress =3D ALIGN_VALUE_LOW (MemoryBase, SIZE_2MB);=0D
+ EndAddress =3D ALIGN_VALUE_UP (MemoryLimit, SIZE_2MB);=0D
+ DEBUG ((DEBUG_INFO, "CreateSecondLevelPagingEntryTable: BaseAddress - 0x=
%016lx, EndAddress - 0x%016lx\n", BaseAddress, EndAddress));=0D
+=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ SecondLevelPagingEntry =3D AllocateZeroPages (1);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "Could not Alloc LVL4 or LVL5 PT. \n"));=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) SecondLevelPagingEntry, EFI=
_PAGES_TO_SIZE (1));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINT=
N) SecondLevelPagingEntry));=0D
+ //=0D
+ // If no access is needed, just create not present entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx Access 0\n", (UI=
NT64) (UINTN) SecondLevelPagingEntry));=0D
+ return SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ Is5LevelPaging =3D VtdUnitInfo->Is5LevelPaging;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D RShiftU64 (EndAddress - 1, 48) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO, " Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start,=
Lvl5End));=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+=0D
+ Lvl4PagesStart =3D (Lvl5Start<<9) | Lvl4Start;=0D
+ Lvl4PagesEnd =3D (Lvl5End<<9) | Lvl4End;=0D
+ DEBUG ((DEBUG_INFO, " Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", =
Lvl4PagesStart, Lvl4PagesEnd));=0D
+=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) SecondLevelPagingEnt=
ry;=0D
+ } else {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D Lvl5Start;=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO, " Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start,=
Lvl4End));=0D
+=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) SecondLevelPagingEnt=
ry;=0D
+ }=0D
+=0D
+ for (Index5 =3D Lvl5Start; Index5 <=3D Lvl5End; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ Lvl5PtEntry[Index5].Uint64 =3D (UINT64) (UINTN) AllocateZeroPages =
(1);=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!=
!\n", Index5));=0D
+ ASSERT (FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl5PtEntry[Index5].Uin=
t64, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+ Lvl4Start =3D Lvl4PagesStart & 0x1FF;=0D
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {=0D
+ Lvl4End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;=0D
+ Lvl4PagesStart =3D (Index5+1)<<9;=0D
+ } else {=0D
+ Lvl4End =3D Lvl4PagesEnd & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, " Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\=
n", Index5, Lvl4Start, Lvl4End));=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTD_64BITS=
_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Addre=
ssHi);=0D
+ }=0D
+=0D
+ for (Index4 =3D Lvl4Start; Index4 <=3D Lvl4End; Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ Lvl4PtEntry[Index4].Uint64 =3D (UINT64) (UINTN) AllocateZeroPages =
(1);=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!=
!\n", Index4));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl4PtEntry[Index4].Uin=
t64, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl3Start =3D RShiftU64 (BaseAddress, 30) & 0x1FF;=0D
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=3D EndAddres=
s) {=0D
+ Lvl3End =3D SIZE_4KB / sizeof (VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;=
=0D
+ } else {=0D
+ Lvl3End =3D RShiftU64 (EndAddress - 1, 30) & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, " Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\=
n", Index4, Lvl3Start, Lvl3End));=0D
+=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTD_64BITS=
_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Addre=
ssHi);=0D
+ for (Index3 =3D Lvl3Start; Index3 <=3D Lvl3End; Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ Lvl3PtEntry[Index3].Uint64 =3D (UINT64) (UINTN) AllocateZeroPage=
s (1);=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x=
%x)!!!!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl3PtEntry[Index3].U=
int64, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_=
IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTD_64BI=
TS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Add=
ressHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ Lvl2PtEntry[Index2].Uint64 =3D BaseAddress;=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuA=
ccess);=0D
+ Lvl2PtEntry[Index2].Bits.PageSize =3D 1;=0D
+ BaseAddress +=3D SIZE_2MB;=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl2PtEntry, SIZE_4KB);=
=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &Lvl3PtEntry[Lvl3Start], =
(UINTN) &Lvl3PtEntry[Lvl3End + 1] - (UINTN) &Lvl3PtEntry[Lvl3Start]);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &Lvl4PtEntry[Lvl4Start], (U=
INTN) &Lvl4PtEntry[Lvl4End + 1] - (UINTN) &Lvl4PtEntry[Lvl4Start]);=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &Lvl5PtEntry[Lvl5Start], (UIN=
TN) &Lvl5PtEntry[Lvl5End + 1] - (UINTN) &Lvl5PtEntry[Lvl5Start]);=0D
+=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINT=
N) SecondLevelPagingEntry));=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Create context entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS The context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create context entry=
.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+CreateContextEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ UINTN EntryTablePages;=0D
+ VOID *Buffer;=0D
+ UINTN RootIndex;=0D
+ UINTN ContextIndex;=0D
+ VTD_ROOT_ENTRY *RootEntryBase;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ if (VtdUnitInfo->RootEntryTable !=3D 0) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTR=
Y_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CON=
TEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER);=
=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_ERROR, "RootEntryTable address - 0x%x\n", Buffer));=0D
+ VtdUnitInfo->RootEntryTable =3D (UINTN) Buffer;=0D
+ VtdUnitInfo->RootEntryTablePageSize =3D EntryTablePages;=0D
+ RootEntryBase =3D (VTD_ROOT_ENTRY *) Buffer;=0D
+ Buffer =3D (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));=0D
+ ASSERT(FALSE);=0D
+ }=0D
+=0D
+ for (RootIndex =3D 0; RootIndex < VTD_ROOT_ENTRY_NUMBER; RootIndex++) {=
=0D
+ SourceId.Index.RootIndex =3D (UINT8) RootIndex;=0D
+=0D
+ RootEntry =3D &RootEntryBase[SourceId.Index.RootIndex];=0D
+ RootEntry->Bits.ContextTablePointerLo =3D (UINT32) RShiftU64 ((UINT64=
) (UINTN) Buffer, 12);=0D
+ RootEntry->Bits.ContextTablePointerHi =3D (UINT32) RShiftU64 ((UINT64=
) (UINTN) Buffer, 32);=0D
+ RootEntry->Bits.Present =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS=
(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointer=
Hi);=0D
+=0D
+ for (ContextIndex =3D 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; Cont=
extIndex++) {=0D
+ SourceId.Index.ContextIndex =3D (UINT8) ContextIndex;=0D
+ ContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex];=0D
+=0D
+ ContextEntry->Bits.TranslationType =3D 0;=0D
+ ContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ContextEntry->Bits.Present =3D 0;=0D
+=0D
+ ContextEntry->Bits.AddressWidth =3D VtdUnitInfo->Is5LevelPaging ? 0x=
3 : 0x2;=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry !=3D 0) {=0D
+ SecondLevelPagingEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) VtdUn=
itInfo->FixedSecondLevelPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry,=
12);=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32=
) Pt;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32=
) RShiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)VtdU=
nitInfo->CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdUnitInfo, VtdUnitInfo->RootEntryTable, EFI_PAGE=
S_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended cont=
ext entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ UINTN EntryTablePages;=0D
+ VOID *Buffer;=0D
+ UINTN RootIndex;=0D
+ UINTN ContextIndex;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntryBase;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ if (VtdUnitInfo->ExtRootEntryTable !=3D 0) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_=
ENTRY_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD=
_CONTEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER);=
=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO, "Could not Alloc Root Entry Table !\n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_ERROR, "ExtRootEntryTable address - 0x%x\n", Buffer));=0D
+ VtdUnitInfo->ExtRootEntryTable =3D (UINTN) Buffer;=0D
+ VtdUnitInfo->ExtRootEntryTablePageSize =3D EntryTablePages;=0D
+ ExtRootEntryBase =3D (VTD_EXT_ROOT_ENTRY *) Buffer;=0D
+ Buffer =3D (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));=0D
+ ASSERT(FALSE);=0D
+ }=0D
+=0D
+ for (RootIndex =3D 0; RootIndex < VTD_ROOT_ENTRY_NUMBER; RootIndex++) {=
=0D
+ SourceId.Index.RootIndex =3D (UINT8)RootIndex;=0D
+=0D
+ ExtRootEntry =3D &ExtRootEntryBase[SourceId.Index.RootIndex];=0D
+ ExtRootEntry->Bits.LowerContextTablePointerLo =3D (UINT32) RShiftU64 =
((UINT64) (UINTN) Buffer, 12);=0D
+ ExtRootEntry->Bits.LowerContextTablePointerHi =3D (UINT32) RShiftU64 =
((UINT64) (UINTN) Buffer, 32);=0D
+ ExtRootEntry->Bits.LowerPresent =3D 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerLo =3D (UINT32) RShiftU64 =
((UINT64) (UINTN) Buffer, 12) + 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerHi =3D (UINT32) RShiftU64 =
(RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);=0D
+ ExtRootEntry->Bits.UpperPresent =3D 1;=0D
+ Buffer =3D (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_=
ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.=
LowerContextTablePointerHi);=0D
+=0D
+ for (ContextIndex =3D 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; Cont=
extIndex++) {=0D
+ SourceId.Index.ContextIndex =3D (UINT8) ContextIndex;=0D
+ ExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.ContextInde=
x];=0D
+=0D
+ ExtContextEntry->Bits.TranslationType =3D 0;=0D
+ ExtContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ExtContextEntry->Bits.Present =3D 0;=0D
+=0D
+ ExtContextEntry->Bits.AddressWidth =3D VtdUnitInfo->Is5LevelPaging ?=
0x3 : 0x2;=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry !=3D 0) {=0D
+ SecondLevelPagingEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) VtdUn=
itInfo->FixedSecondLevelPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry,=
12);=0D
+=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UIN=
T32) Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UIN=
T32) RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8) ((UINTN)=
VtdUnitInfo->CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable, EFI_P=
AGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+#define VTD_PG_R BIT0=0D
+#define VTD_PG_W BIT1=0D
+#define VTD_PG_X BIT2=0D
+#define VTD_PG_EMT (BIT3 | BIT4 | BIT5)=0D
+#define VTD_PG_TM (BIT62)=0D
+=0D
+#define VTD_PG_PS BIT7=0D
+=0D
+#define PAGE_PROGATE_BITS (VTD_PG_TM | VTD_PG_EMT | VTD_PG_W | VT=
D_PG_R)=0D
+=0D
+#define PAGING_4K_MASK 0xFFF=0D
+#define PAGING_2M_MASK 0x1FFFFF=0D
+#define PAGING_1G_MASK 0x3FFFFFFF=0D
+=0D
+#define PAGING_VTD_INDEX_MASK 0x1FF=0D
+=0D
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull=0D
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull=0D
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull=0D
+=0D
+typedef enum {=0D
+ PageNone,=0D
+ Page4K,=0D
+ Page2M,=0D
+ Page1G,=0D
+} PAGE_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ PAGE_ATTRIBUTE Attribute;=0D
+ UINT64 Length;=0D
+ UINT64 AddressMask;=0D
+} PAGE_ATTRIBUTE_TABLE;=0D
+=0D
+PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D {=0D
+ {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},=0D
+ {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},=0D
+ {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},=0D
+};=0D
+=0D
+/**=0D
+ Return length according to page attributes.=0D
+=0D
+ @param[in] PageAttributes The page attribute of the page entry.=0D
+=0D
+ @return The length of page entry.=0D
+**/=0D
+UINTN=0D
+PageAttributeToLength (=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ for (Index =3D 0; Index < sizeof (mPageAttributeTable) / sizeof (mPageAt=
tributeTable[0]); Index++) {=0D
+ if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) {=0D
+ return (UINTN) mPageAttributeTable[Index].Length;=0D
+ }=0D
+ }=0D
+ return 0;=0D
+}=0D
+=0D
+/**=0D
+ Return page table entry to match the address.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in V=
Td table for the device.=0D
+ @param[in] Address The address to be checked.=0D
+ @param[out] PageAttributes The page attribute of the page ent=
ry.=0D
+=0D
+ @return The page entry.=0D
+**/=0D
+VOID *=0D
+GetSecondLevelPageTableEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN PHYSICAL_ADDRESS Address,=0D
+ OUT PAGE_ATTRIBUTE *PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index1;=0D
+ UINTN Index2;=0D
+ UINTN Index3;=0D
+ UINTN Index4;=0D
+ UINTN Index5;=0D
+ UINT64 *L1PageTable;=0D
+ UINT64 *L2PageTable;=0D
+ UINT64 *L3PageTable;=0D
+ UINT64 *L4PageTable;=0D
+ UINT64 *L5PageTable;=0D
+ BOOLEAN Is5LevelPaging;=0D
+=0D
+ Index5 =3D ((UINTN) RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;=0D
+ Index4 =3D ((UINTN) RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;=0D
+ Index3 =3D ((UINTN) Address >> 30) & PAGING_VTD_INDEX_MASK;=0D
+ Index2 =3D ((UINTN) Address >> 21) & PAGING_VTD_INDEX_MASK;=0D
+ Index1 =3D ((UINTN) Address >> 12) & PAGING_VTD_INDEX_MASK;=0D
+=0D
+ Is5LevelPaging =3D VtdUnitInfo->Is5LevelPaging;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ L5PageTable =3D (UINT64 *) SecondLevelPagingEntry;=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ L5PageTable[Index5] =3D (UINT64) (UINTN) AllocateZeroPages (1);=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\=
n", Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) L5PageTable[Index5], SIZE=
_4KB);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *=
) &L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE)=
;=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L5PageTable[Index5], siz=
eof(L5PageTable[Index5]));=0D
+ }=0D
+ L4PageTable =3D (UINT64 *) (UINTN) (L5PageTable[Index5] & PAGING_4K_AD=
DRESS_MASK_64);=0D
+ } else {=0D
+ L4PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ L4PageTable[Index4] =3D (UINT64) (UINTN) AllocateZeroPages (1);=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n"=
, Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) L4PageTable[Index4], SIZE_4=
KB);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *) =
&L4PageTable[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L4PageTable[Index4], sizeo=
f(L4PageTable[Index4]));=0D
+ }=0D
+=0D
+ L3PageTable =3D (UINT64 *) (UINTN) (L4PageTable[Index4] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ L3PageTable[Index3] =3D (UINT64) (UINTN) AllocateZeroPages (1);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!=
!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) L3PageTable[Index3], SIZE_4=
KB);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *) =
&L3PageTable[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L3PageTable[Index3], sizeo=
f (L3PageTable[Index3]));=0D
+ }=0D
+ if ((L3PageTable[Index3] & VTD_PG_PS) !=3D 0) {=0D
+ // 1G=0D
+ *PageAttribute =3D Page1G;=0D
+ return &L3PageTable[Index3];=0D
+ }=0D
+=0D
+ L2PageTable =3D (UINT64 *) (UINTN) (L3PageTable[Index3] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ if (L2PageTable[Index2] =3D=3D 0) {=0D
+ L2PageTable[Index2] =3D Address & PAGING_2M_ADDRESS_MASK_64;=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *) =
&L2PageTable[Index2], 0);=0D
+ L2PageTable[Index2] |=3D VTD_PG_PS;=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L2PageTable[Index2], sizeo=
f (L2PageTable[Index2]));=0D
+ }=0D
+ if ((L2PageTable[Index2] & VTD_PG_PS) !=3D 0) {=0D
+ // 2M=0D
+ *PageAttribute =3D Page2M;=0D
+ return &L2PageTable[Index2];=0D
+ }=0D
+=0D
+ // 4k=0D
+ L1PageTable =3D (UINT64 *) (UINTN) (L2PageTable[Index2] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ if ((L1PageTable[Index1] =3D=3D 0) && (Address !=3D 0)) {=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ *PageAttribute =3D Page4K;=0D
+ return &L1PageTable[Index1];=0D
+}=0D
+=0D
+/**=0D
+ Modify memory attributes of page entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] PageEntry The page entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[out] IsModified TRUE means page table modified. FALSE mean=
s page table not modified.=0D
+**/=0D
+VOID=0D
+ConvertSecondLevelPageEntryAttribute (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN UINT64 IoMmuAccess,=0D
+ OUT BOOLEAN *IsModified=0D
+ )=0D
+{=0D
+ UINT64 CurrentPageEntry;=0D
+ UINT64 NewPageEntry;=0D
+=0D
+ CurrentPageEntry =3D PageEntry->Uint64;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) PageEntry, sizeof(*PageEntry)=
);=0D
+ NewPageEntry =3D PageEntry->Uint64;=0D
+ if (CurrentPageEntry !=3D NewPageEntry) {=0D
+ *IsModified =3D TRUE;=0D
+ DEBUG ((DEBUG_VERBOSE, "ConvertSecondLevelPageEntryAttribute 0x%lx", C=
urrentPageEntry));=0D
+ DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));=0D
+ } else {=0D
+ *IsModified =3D FALSE;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ This function returns if there is need to split page entry.=0D
+=0D
+ @param[in] BaseAddress The base address to be checked.=0D
+ @param[in] Length The length to be checked.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+=0D
+ @retval SplitAttributes on if there is need to split page entry.=0D
+**/=0D
+PAGE_ATTRIBUTE=0D
+NeedSplitPage (=0D
+ IN PHYSICAL_ADDRESS BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINT64 PageEntryLength;=0D
+=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+=0D
+ if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D Pag=
eEntryLength)) {=0D
+ return PageNone;=0D
+ }=0D
+=0D
+ if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) {=0D
+ return Page4K;=0D
+ }=0D
+=0D
+ return Page2M;=0D
+}=0D
+=0D
+/**=0D
+ This function splits one page entry to small page entries.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] PageEntry The page entry to be splitted.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+ @param[in] SplitAttribute How to split the page entry.=0D
+=0D
+ @retval RETURN_SUCCESS The page entry is splitted.=0D
+ @retval RETURN_UNSUPPORTED The page entry does not support to be =
splitted.=0D
+ @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.=0D
+**/=0D
+RETURN_STATUS=0D
+SplitSecondLevelPage (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN PAGE_ATTRIBUTE PageAttribute,=0D
+ IN PAGE_ATTRIBUTE SplitAttribute=0D
+ )=0D
+{=0D
+ UINT64 BaseAddress;=0D
+ UINT64 *NewPageEntry;=0D
+ UINTN Index;=0D
+=0D
+ ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G);=0D
+=0D
+ if (PageAttribute =3D=3D Page2M) {=0D
+ //=0D
+ // Split 2M to 4K=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page4K);=0D
+ if (SplitAttribute =3D=3D Page4K) {=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_INFO, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_2M_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | (PageEn=
try->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)PageEntry, sizeof(*PageEnt=
ry));=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else if (PageAttribute =3D=3D Page1G) {=0D
+ //=0D
+ // Split 1G to 2M=0D
+ // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K =
to get more compact page table.=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K);=
=0D
+ if ((SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K)) {=
=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_INFO, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_1G_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | VTD_PG_=
PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)PageEntry, sizeof(*PageEnt=
ry));=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory on second level page entry=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetSecondLevelPagingAttribute (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry;=0D
+ PAGE_ATTRIBUTE PageAttribute;=0D
+ UINTN PageEntryLength;=0D
+ PAGE_ATTRIBUTE SplitAttribute;=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN IsEntryModified;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "SetSecondLevelPagingAttribute (0x%016lx - 0x%016lx =
: %x) \n", BaseAddress, Length, IoMmuAccess));=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry Base - 0x%x\n", SecondLeve=
lPagingEntry));=0D
+=0D
+ if (BaseAddress !=3D ALIGN_VALUE(BaseAddress, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ if (Length !=3D ALIGN_VALUE(Length, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ while (Length !=3D 0) {=0D
+ PageEntry =3D GetSecondLevelPageTableEntry (VtdUnitInfo, SecondLevelPa=
gingEntry, BaseAddress, &PageAttribute);=0D
+ if (PageEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+ SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageAttribute);=
=0D
+ if (SplitAttribute =3D=3D PageNone) {=0D
+ ConvertSecondLevelPageEntryAttribute (VtdUnitInfo, PageEntry, IoMmuA=
ccess, &IsEntryModified);=0D
+ //=0D
+ // Convert success, move to next=0D
+ //=0D
+ BaseAddress +=3D PageEntryLength;=0D
+ Length -=3D PageEntryLength;=0D
+ } else {=0D
+ Status =3D SplitSecondLevelPage (VtdUnitInfo, PageEntry, PageAttribu=
te, SplitAttribute);=0D
+ if (RETURN_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ //=0D
+ // Just split current page=0D
+ // Convert success in next around=0D
+ //=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create Fixed Second Level Paging Entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCES Setup translation table fail.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+CreateFixedSecondLevelPagingEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT64 IoMmuAccess;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry !=3D 0) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ VtdUnitInfo->FixedSecondLevelPagingEntry =3D (UINTN) CreateSecondLevelPa=
gingEntryTable (VtdUnitInfo, NULL, 0, SIZE_4GB, 0);=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA (Hob);=0D
+ BaseAddress =3D DmaBufferInfo->DmaBufferBase;=0D
+ Length =3D DmaBufferInfo->DmaBufferSize;=0D
+ IoMmuAccess =3D EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " BaseAddress =3D 0x%lx\n", BaseAddress));=0D
+ DEBUG ((DEBUG_INFO, " Length =3D 0x%lx\n", Length));=0D
+ DEBUG ((DEBUG_INFO, " IoMmuAccess =3D 0x%lx\n", IoMmuAccess));=0D
+=0D
+ Status =3D SetSecondLevelPagingAttribute (VtdUnitInfo, (VTD_SECOND_LEVEL=
_PAGING_ENTRY*) VtdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Leng=
th, IoMmuAccess);=0D
+=0D
+ return Status;=0D
+}=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCES Setup translation table fail.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+ if (VtdUnitInfo->Done) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Status =3D CreateFixedSecondLevelPagingEntry (VtdUnitInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_INFO, "CreateFixedSecondLevelPagingEntry failed - %r\n=
", Status));=0D
+ return Status;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ECapReg.Bits.SMTS) {=0D
+ if (VtdUnitInfo->ECapReg.Bits.DEP_24) {=0D
+ DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));=0D
+ ASSERT(FALSE);=0D
+ Status =3D EFI_UNSUPPORTED;=0D
+ } else {=0D
+ Status =3D CreateContextEntry (VtdUnitInfo);=0D
+ }=0D
+ } else {=0D
+ if (VtdUnitInfo->ECapReg.Bits.DEP_24) {=0D
+ //=0D
+ // To compatible with pervious VTd engine=0D
+ // It was ECS(Extended Context Support) bit.=0D
+ //=0D
+ Status =3D CreateExtContextEntry (VtdUnitInfo);=0D
+ } else {=0D
+ Status =3D CreateContextEntry (VtdUnitInfo);=0D
+ }=0D
+ }=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHob.h b/S=
ilicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHob.h
new file mode 100644
index 000000000..cfddce995
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHob.h
@@ -0,0 +1,151 @@
+/** @file=0D
+ The definition for VTD Log Data Hob.=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+**/=0D
+=0D
+=0D
+#ifndef _VTD_LOG_DATA_HOB_H_=0D
+#define _VTD_LOG_DATA_HOB_H_=0D
+=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+#define VTDLOG_LOG_TYPE(_id_) ((UINT64) 1 << (_id_))=0D
+=0D
+typedef enum {=0D
+ VTDLOG_PEI_BASIC =3D 0, // Start ID for PEI bas=
ic log=0D
+ VTDLOG_PEI_PRE_MEM_DMA_PROTECT =3D 1, // PRE-MEM phase=0D
+ VTDLOG_PEI_PMR_LOW_MEMORY_RANGE =3D 2,=0D
+ VTDLOG_PEI_PMR_HIGH_MEMORY_RANGE =3D 3,=0D
+ VTDLOG_PEI_PROTECT_MEMORY_RANGE =3D 4,=0D
+ VTDLOG_PEI_POST_MEM_ENABLE_DMA_PROTECT =3D 5,=0D
+ VTDLOG_PEI_POST_MEM_DISABLE_DMA_PROTECT =3D 6,=0D
+ VTDLOG_PEI_QUEUED_INVALIDATION =3D 7,=0D
+ VTDLOG_PEI_REGISTER =3D 8,=0D
+ VTDLOG_PEI_VTD_ERROR =3D 9,=0D
+=0D
+ VTDLOG_PEI_ADVANCED =3D 16, // Start ID for PEI ad=
vanced log=0D
+ VTDLOG_PEI_PPI_ALLOC_BUFFER =3D 17,=0D
+ VTDLOG_PEI_PPI_MAP =3D 18,=0D
+=0D
+ VTDLOG_DXE_BASIC =3D 24, // Start ID for DXE ba=
sic log=0D
+ VTDLOG_DXE_DMAR_TABLE =3D 25,=0D
+ VTDLOG_DXE_SETUP_VTD =3D 26,=0D
+ VTDLOG_DXE_PCI_DEVICE =3D 27,=0D
+ VTDLOG_DXE_REGISTER =3D 28,=0D
+ VTDLOG_DXE_ENABLE_DMAR =3D 29,=0D
+ VTDLOG_DXE_DISABLE_DMAR =3D 30,=0D
+ VTDLOG_DXE_DISABLE_PMR =3D 31,=0D
+ VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL =3D 32,=0D
+ VTDLOG_DXE_QUEUED_INVALIDATION =3D 33, =0D
+=0D
+ VTDLOG_DXE_ADVANCED =3D 44, // Start ID for DXE ad=
vanced log=0D
+ VTDLOG_DXE_IOMMU_ALLOC_BUFFER =3D 45,=0D
+ VTDLOG_DXE_IOMMU_FREE_BUFFER =3D 46,=0D
+ VTDLOG_DXE_IOMMU_MAP =3D 47,=0D
+ VTDLOG_DXE_IOMMU_UNMAP =3D 48,=0D
+ VTDLOG_DXE_IOMMU_SET_ATTRIBUTE =3D 49,=0D
+ VTDLOG_DXE_ROOT_TABLE =3D 50,=0D
+} VTDLOG_EVENT_TYPE;=0D
+=0D
+#define VTD_LOG_PEI_PRE_MEM_BAR_MAX 8=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_BASIC / VTDLOG_DXE_BASIC=0D
+//=0D
+#define VTD_LOG_ERROR_BUFFER_FULL (1<<0)=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_PRE_MEM_DMA_PROTECT_MODE=0D
+//=0D
+#define VTD_LOG_PEI_PRE_MEM_NOT_USED 0=0D
+#define VTD_LOG_PEI_PRE_MEM_DISABLE 1=0D
+#define VTD_LOG_PEI_PRE_MEM_ADM 2=0D
+#define VTD_LOG_PEI_PRE_MEM_TE 3=0D
+#define VTD_LOG_PEI_PRE_MEM_PMR 4=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_QUEUED_INVALIDATION=0D
+//=0D
+#define VTD_LOG_QI_DISABLE 0=0D
+#define VTD_LOG_QI_ENABLE 1=0D
+#define VTD_LOG_QI_ERROR_OUT_OF_RESOURCES 2=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_VTD_ERROR=0D
+//=0D
+#define VTD_LOG_PEI_VTD_ERROR_PPI_ALLOC 1=0D
+#define VTD_LOG_PEI_VTD_ERROR_PPI_MAP 2=0D
+=0D
+// Code of VTDLOG_PEI_REGISTER / VTDLOG_DXE_REGISTER=0D
+#define VTDLOG_REGISTER_ALL 0=0D
+#define VTDLOG_REGISTER_THIN 1=0D
+#define VTDLOG_REGISTER_QI 2=0D
+=0D
+#pragma pack(1)=0D
+=0D
+//=0D
+// Item head=0D
+//=0D
+typedef struct {=0D
+ UINT32 DataSize;=0D
+ UINT64 LogType;=0D
+ UINT64 Timestamp;=0D
+}VTDLOG_EVENT_HEADER;=0D
+=0D
+//=0D
+// Struct for type =3D VTDLOG_PEI_REGISTER=0D
+// VTDLOG_DXE_REGISTER=0D
+// VTDLOG_DXE_DMAR_TABLE=0D
+// VTDLOG_DXE_IOMMU_SET_ATTRIBUTE=0D
+// VTDLOG_DXE_PCI_DEVICE=0D
+// VTDLOG_DXE_ROOT_TABLE=0D
+//=0D
+typedef struct {=0D
+ VTDLOG_EVENT_HEADER Header;=0D
+ UINT64 Param;=0D
+ UINT8 Data[1];=0D
+} VTDLOG_EVENT_CONTEXT;=0D
+=0D
+//=0D
+// Struct for rest of the types=0D
+//=0D
+typedef struct {=0D
+ VTDLOG_EVENT_HEADER Header;=0D
+ UINT64 Data1;=0D
+ UINT64 Data2;=0D
+}VTDLOG_EVENT_2PARAM;=0D
+=0D
+//=0D
+// Struct for VTd log event=0D
+//=0D
+typedef union{=0D
+ VTDLOG_EVENT_HEADER EventHeader;=0D
+ VTDLOG_EVENT_2PARAM CommenEvent;=0D
+ VTDLOG_EVENT_CONTEXT ContextEvent;=0D
+} VTDLOG_EVENT;=0D
+=0D
+//=0D
+// Information for PEI pre-memory phase=0D
+//=0D
+typedef struct {=0D
+ UINT8 Mode;=0D
+ UINT8 Status;=0D
+ UINT32 BarAddress;=0D
+} VTDLOG_PEI_PRE_MEM_INFO;=0D
+=0D
+//=0D
+// Buffer struct for PEI phase=0D
+//=0D
+typedef struct {=0D
+ UINT8 VtdLogPeiError;=0D
+ VTDLOG_PEI_PRE_MEM_INFO PreMemInfo[VTD_LOG_PEI_PRE_MEM_BAR_MAX];=0D
+ UINT32 PostMemBufferUsed;=0D
+ UINT64 PostMemBuffer;=0D
+} VTDLOG_PEI_BUFFER_HOB;=0D
+=0D
+#pragma pack()=0D
+=0D
+#endif // _VTD_LOG_DATA_HOB_H_=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdPeiDxeLi=
b.h b/Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdPeiDxeLib.h
new file mode 100644
index 000000000..c0a137a77
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdPeiDxeLib.h
@@ -0,0 +1,329 @@
+/** @file=0D
+ Intel VTd library definitions.=0D
+=0D
+ Copyright (c) 2023 Intel Corporation. All rights reserved. <BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+**/=0D
+#ifndef _INTEL_VTD_PEI_DXE_LIB_H_=0D
+#define _INTEL_VTD_PEI_DXE_LIB_H_=0D
+=0D
+//=0D
+// Include files=0D
+//=0D
+#include <Uefi/UefiBaseType.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Protocol/VtdLog.h>=0D
+#include <Protocol/PlatformVtdPolicy.h>=0D
+=0D
+#if defined (EXT_CALLBACK)=0D
+ #define _VTDLIB_DEBUG(PrintLevel, ...) =
\=0D
+ do { =
\=0D
+ VtdLogEventCallback (Context, CallbackHandle, PrintLevel, ##__VA_ARG=
S__); \=0D
+ } while (FALSE)=0D
+ #define VTDLIB_DEBUG(Expression) _VTDLIB_DEBUG Expression=0D
+#else=0D
+ #define VTDLIB_DEBUG(Expression) DEBUG(Expression)=0D
+#endif=0D
+=0D
+#pragma pack(1)=0D
+=0D
+typedef struct {=0D
+ UINT8 DeviceType;=0D
+ VTD_SOURCE_ID PciSourceId;=0D
+ EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId;=0D
+ // for statistic analysis=0D
+ UINT64 AccessCount;=0D
+} PCI_DEVICE_DATA;=0D
+=0D
+typedef struct {=0D
+ BOOLEAN IncludeAllFlag;=0D
+ UINT16 Segment;=0D
+ UINT32 PciDeviceDataMaxNumber;=0D
+ UINT32 PciDeviceDataNumber;=0D
+ PCI_DEVICE_DATA PciDeviceData[1];=0D
+} PCI_DEVICE_INFORMATION;=0D
+=0D
+typedef struct {=0D
+ UINT64 Uint64Lo;=0D
+ UINT64 Uint64Hi;=0D
+}VTD_UINT128;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT32 VerReg;=0D
+ UINT64 CapReg;=0D
+ UINT64 EcapReg;=0D
+ UINT32 GstsReg;=0D
+ UINT64 RtaddrReg;=0D
+ UINT64 CcmdReg;=0D
+ UINT32 FstsReg;=0D
+ UINT32 FectlReg;=0D
+ UINT32 FedataReg;=0D
+ UINT32 FeaddrReg;=0D
+ UINT32 FeuaddrReg;=0D
+ UINT64 IqercdReg;=0D
+ UINT64 IvaReg;=0D
+ UINT64 IotlbReg;=0D
+ UINT16 FrcdRegNum; // Number of FRCD Register=
s=0D
+ VTD_UINT128 FrcdReg[1];=0D
+} VTD_REGESTER_INFO;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT32 FstsReg;=0D
+ UINT64 IqercdReg;=0D
+} VTD_REGESTER_QI_INFO;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT32 GstsReg;=0D
+ UINT64 RtaddrReg;=0D
+ UINT32 FstsReg;=0D
+ UINT32 FectlReg;=0D
+ UINT64 IqercdReg;=0D
+ UINT16 FrcdRegNum; // Number of FRCD Register=
s=0D
+ VTD_UINT128 FrcdReg[1];=0D
+} VTD_REGESTER_THIN_INFO;=0D
+=0D
+typedef struct {=0D
+ VTD_SOURCE_ID SourceId;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ UINT64 Length;=0D
+ UINT64 IoMmuAccess;=0D
+ EFI_STATUS Status;=0D
+} VTD_PROTOCOL_SET_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT64 TableAddress;=0D
+ BOOLEAN Is5LevelPaging;=0D
+} VTD_ROOT_TABLE_INFO;=0D
+=0D
+#pragma pack()=0D
+=0D
+/**=0D
+ Callback function of VTd lib handle strings.=0D
+=0D
+ @param[in] Context Context=0D
+ @param[in] ErrorLevel The error level of the debug message.=
=0D
+ @param[in] Buffer Event string=0D
+**/=0D
+typedef=0D
+VOID=0D
+(EFIAPI *EDKII_VTD_LIB_STRING_CB) (=0D
+ IN VOID *Context,=0D
+ IN UINTN ErrorLevel,=0D
+ IN CHAR8 *Buffer=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event Context=0D
+ @param[in out] CallbackHandle Callback Handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmar (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ );=0D
+=0D
+/**=0D
+ Dump DRHD DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event Context=0D
+ @param[in out] CallbackHandle Callback Handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmarDrhd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ );=0D
+=0D
+/**=0D
+ Dump the PCI device information managed by this VTd engine.=0D
+=0D
+ @param[in] Context Event Context=0D
+ @param[in out] CallbackHandle Callback Handler=0D
+ @param[in] PciDeviceInfo PCI device information=0D
+**/=0D
+VOID=0D
+VtdLibDumpPciDeviceInfo (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN PCI_DEVICE_INFORMATION *PciDeviceInfo=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] RootEntry DMAR root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_ROOT_ENTRY *RootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR extended context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] ExtRootEntry DMAR extended root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarExtContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers Information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsAll (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_INFO *VtdRegInfo=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers Information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsThin (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_THIN_INFO *VtdRegInfo=0D
+ );=0D
+=0D
+/**=0D
+ Decode log event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event Event struct=0D
+=0D
+ @retval TRUE Decode event success=0D
+ @retval FALSE Unknown event=0D
+**/=0D
+BOOLEAN=0D
+VtdLibDecodeEvent (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT *Event=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTd engine write buffer.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibFlushWriteBuffer (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Clear Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask.=0D
+**/=0D
+VOID=0D
+VtdLibClearGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ );=0D
+=0D
+/**=0D
+ Set Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask.=0D
+**/=0D
+VOID=0D
+VtdLibSetGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ );=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisableDmar (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Disable PMR.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS PMR is disabled.=0D
+ @retval EFI_UNSUPPORTED PMR is not supported.=0D
+ @retval EFI_NOT_STARTED PMR was not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisablePmr (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Disable queued invalidation interface.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibDisableQueuedInvalidationInterface (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+ @param[in] ClearFaultBits Clear Error bits=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+ @retval EFI_DEVICE_ERROR Detect fault, need to clear fault bits=
if ClearFaultBits is FALSE=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibSubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN VOID *Desc,=0D
+ IN BOOLEAN ClearFaultBits=0D
+ );=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h b/Sili=
con/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
new file mode 100644
index 000000000..7c2894e81
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
@@ -0,0 +1,59 @@
+/** @file=0D
+ The definition for VTD Log.=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef __VTD_LOG_PROTOCOL_H__=0D
+#define __VTD_LOG_PROTOCOL_H__=0D
+=0D
+#include <Guid/VtdLogDataHob.h>=0D
+=0D
+#define EDKII_VTD_LOG_PROTOCOL_GUID \=0D
+ { \=0D
+ 0x1e271819, 0xa3ca, 0x481f, { 0xbd, 0xff, 0x92, 0x78, 0x2f, 0x9a, 0x=
99, 0x3c } \=0D
+ }=0D
+=0D
+typedef struct _EDKII_VTD_LOG_PROTOCOL EDKII_VTD_LOG_PROTOCOL;=0D
+=0D
+#define EDKII_VTD_LOG_PROTOCOL_REVISION 0x00010000=0D
+=0D
+/**=0D
+ Callback function of each VTd log event.=0D
+ @param[in] Context Event context=0D
+ @param[in] Header Event header=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+typedef=0D
+VOID=0D
+(EFIAPI *EDKII_VTD_LOG_HANDLE_EVENT) (=0D
+ IN VOID *Context,=0D
+ IN VTDLOG_EVENT_HEADER *Header=0D
+ );=0D
+=0D
+/**=0D
+ Get the VTd log events.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+typedef=0D
+UINT64=0D
+(EFIAPI *EDKII_VTD_LOG_GET_EVENTS) (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ );=0D
+=0D
+struct _EDKII_VTD_LOG_PROTOCOL {=0D
+ UINT64 Revision;=0D
+ EDKII_VTD_LOG_GET_EVENTS GetEvents;=0D
+};=0D
+=0D
+extern EFI_GUID gEdkiiVTdLogProtocolGuid;=0D
+=0D
+#endif=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/In=
tel/IntelSiliconPkg/IntelSiliconPkg.dec
index cad22acda..ec8690a8d 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -73,6 +73,9 @@
## HOB GUID to get memory information after MRC is done. The hob data wi=
ll be used to set the PMR ranges=0D
gVtdPmrInfoDataHobGuid =3D {0x6fb61645, 0xf168, 0x46be, { 0x80, 0xec, 0x=
b5, 0x02, 0x38, 0x5e, 0xe7, 0xe7 } }=0D
=0D
+ ## HOB GUID to get VTd log data.=0D
+ gVTdLogBufferHobGuid =3D {0xc8049121, 0xdf91, 0x4dfd, { 0xad, 0xcb, 0x1c=
, 0x55, 0x85, 0x09, 0x6d, 0x3b } }=0D
+=0D
## Include/Guid/MicrocodeShadowInfoHob.h=0D
gEdkiiMicrocodeShadowInfoHobGuid =3D { 0x658903f9, 0xda66, 0x460d, { 0x8=
b, 0xb0, 0x9d, 0x2d, 0xdf, 0x65, 0x44, 0x59 } }=0D
=0D
@@ -119,6 +122,8 @@
gPchSmmSpi2ProtocolGuid =3D { 0x2d1c0c43, 0x20d3, 0x40ae, { 0x99, 0x07, =
0x2d, 0xf0, 0xe7, 0x91, 0x21, 0xa5 } }=0D
=0D
gEdkiiPlatformVTdPolicyProtocolGuid =3D { 0x3d17e448, 0x466, 0x4e20, { 0=
x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }}=0D
+ gEdkiiVTdLogProtocolGuid =3D { 0x1e271819, 0xa3ca, 0x481f, { 0xbd, 0xff,=
0x92, 0x78, 0x2f, 0x9a, 0x99, 0x3c }}=0D
+=0D
gIntelDieInfoProtocolGuid =3D { 0xAED8A0A1, 0xFDE6, 0x4CF2, { 0xA3, 0x85=
, 0x08, 0xF1, 0x25, 0xF2, 0x40, 0x37 }}=0D
=0D
## Protocol for device security policy.=0D
@@ -207,3 +212,19 @@
# non-zero: The size of an additional NVS region following the Regular =
variable region.<BR>=0D
# @Prompt Additional NVS Region Size.=0D
gIntelSiliconPkgTokenSpaceGuid.PcdFlashNvStorageAdditionalSize|0x0000000=
0|UINT32|0x0000000F=0D
+=0D
+ ## Declares VTd LOG Output Level.<BR><BR>=0D
+ # 0 : Disable VTd Log=0D
+ # 1 : Enable Basic Log=0D
+ # 2 : Enable All Log=0D
+ # @Prompt The VTd Log Output Level.=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel|0x02|UINT8|0x00000017=0D
+=0D
+ ## Declares VTd PEI POST-MEM LOG buffer size.<BR><BR>=0D
+ # @Prompt The VTd PEI Post-Mem Log buffer size. 8k=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize|0x00002000|=
UINT32|0x00000019=0D
+=0D
+ ## Declares VTd DXE LOG buffer size.<BR><BR>=0D
+ # @Prompt The VTd DXE Log buffer size. 4M=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdDxeLogBufferSize|0x00400000|UINT32|=
0x0000001A=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc b/Silicon/In=
tel/IntelSiliconPkg/IntelSiliconPkg.dsc
index 170eb480a..c8ff40b38 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
@@ -45,6 +45,7 @@
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBoo=
tServicesTableLib.inf=0D
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntry=
Point.inf=0D
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseV=
ariableFlashInfoLib.inf=0D
+ IntelVTdPeiDxeLib|IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiD=
xeLib.inf=0D
=0D
[LibraryClasses.common.PEIM]=0D
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelV=
TdPeiDxeLib.c b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/Int=
elVTdPeiDxeLib.c
new file mode 100644
index 000000000..67953202b
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiDx=
eLib.c
@@ -0,0 +1,1819 @@
+/** @file=0D
+ Source code file for Intel VTd PEI DXE library.=0D
+=0D
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+//=0D
+// Define the maximum message length that this library supports=0D
+//=0D
+#define MAX_STRING_LENGTH (0x100)=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+/**=0D
+ Produces a Null-terminated ASCII string in an output buffer based on a N=
ull-terminated=0D
+ ASCII format string and variable argument list.=0D
+ =0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] ErrorLevel The error level of the debug message.=0D
+ @param[in] FormatString A Null-terminated ASCII format string.=
=0D
+ @param[in] ... Variable argument list whose contents a=
re accessed based on the format string specified by FormatString.=0D
+=0D
+ @return The number of ASCII characters in the produced output buffer not=
including the=0D
+ Null-terminator.=0D
+**/=0D
+UINTN=0D
+EFIAPI=0D
+VtdLogEventCallback (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN UINTN ErrorLevel,=0D
+ IN CONST CHAR8 *FormatString,=0D
+ ...=0D
+ )=0D
+{=0D
+ CHAR8 Buffer[MAX_STRING_LENGTH];=0D
+ VA_LIST Marker;=0D
+ UINTN NumberOfPrinted;=0D
+=0D
+ if ((CallbackHandle =3D=3D NULL) || (FormatString =3D=3D NULL)) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ VA_START (Marker, FormatString);=0D
+ NumberOfPrinted =3D AsciiVSPrint (Buffer, sizeof (Buffer), FormatString,=
Marker);=0D
+ VA_END (Marker);=0D
+=0D
+ if (NumberOfPrinted > 0) {=0D
+ CallbackHandle (Context, ErrorLevel, Buffer);=0D
+ }=0D
+=0D
+ return NumberOfPrinted;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR DeviceScopeEntry.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarDeviceScopeEntry (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntr=
y=0D
+ )=0D
+{=0D
+ UINTN PciPathNumber;=0D
+ UINTN PciPathIndex;=0D
+ EFI_ACPI_DMAR_PCI_PATH *PciPath;=0D
+=0D
+ if (DmarDeviceScopeEntry =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " * DMA-Remapping Device Scope Entry Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " DMAR Device Scope Entry address ...................... 0x%016lx\n=
" :=0D
+ " DMAR Device Scope Entry address ...................... 0x%08x\n",=
=0D
+ DmarDeviceScopeEntry=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Device Scope Entry Type ............................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Type=0D
+ ));=0D
+ switch (DmarDeviceScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " PCI Endpoint Device\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " PCI Sub-hierachy\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " IOAPIC\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " MSI Capable HPET\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " ACPI Namespace Device\n"=0D
+ ));=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................. 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Enumeration ID ..................................... 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->EnumerationId=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Starting Bus Number ................................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->StartBusNumber=0D
+ ));=0D
+=0D
+ PciPathNumber =3D (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_D=
EVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);=0D
+ PciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);=0D
+ for (PciPathIndex =3D 0; PciPathIndex < PciPathNumber; PciPathIndex++) {=
=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Device ............................................. 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Device=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Function ........................................... 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Function=0D
+ ));=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR SIDP table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Sidp DMAR SIDP table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarSidp (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_SIDP_HEADER *Sidp=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN SidpLen;=0D
+=0D
+ if (Sidp =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " * SoC Integrated Device Property Reporting Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " SIDP address ........................................... 0x%016lx\n=
" :=0D
+ " SIDP address ........................................... 0x%08x\n",=
=0D
+ Sidp=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Sidp->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Sidp->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Sidp->SegmentNumber=0D
+ ));=0D
+=0D
+ SidpLen =3D Sidp->Header.Length - sizeof(EFI_ACPI_DMAR_SIDP_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Sidp + 1);=0D
+ while (SidpLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ SidpLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR SATC table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Satc DMAR SATC table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarSatc (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_SATC_HEADER *Satc=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN SatcLen;=0D
+=0D
+ if (Satc =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * ACPI Soc Integrated Address Translation Cache reporting Str=
ucture *\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " SATC address ........................................... 0x%016lx\n=
" :=0D
+ " SATC address ........................................... 0x%08x\n",=
=0D
+ Satc=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Satc->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Satc->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Satc->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Satc->SegmentNumber=0D
+ ));=0D
+=0D
+ SatcLen =3D Satc->Header.Length - sizeof(EFI_ACPI_DMAR_SATC_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Satc + 1);=0D
+ while (SatcLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ SatcLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ANDD table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Andd DMAR ANDD table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarAndd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_ANDD_HEADER *Andd=0D
+ )=0D
+{=0D
+ if (Andd =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * ACPI Name-space Device Declaration Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " ANDD address ........................................... 0x%016lx\n=
" :=0D
+ " ANDD address ........................................... 0x%08x\n",=
=0D
+ Andd=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Andd->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Andd->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " ACPI Device Number ................................... 0x%02x\n",=
=0D
+ Andd->AcpiDeviceNumber=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " ACPI Object Name ..................................... '%a'\n",=0D
+ (Andd + 1)=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR RHSA table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Rhsa DMAR RHSA table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarRhsa (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_RHSA_HEADER *Rhsa=0D
+ )=0D
+{=0D
+ if (Rhsa =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * Remapping Hardware Status Affinity Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " RHSA address ........................................... 0x%016lx\n=
" :=0D
+ " RHSA address ........................................... 0x%08x\n",=
=0D
+ Rhsa=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Rhsa->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Rhsa->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Register Base Address ................................ 0x%016lx\n=
",=0D
+ Rhsa->RegisterBaseAddress=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Proximity Domain ..................................... 0x%08x\n",=
=0D
+ Rhsa->ProximityDomain=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ATSR table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Atsr DMAR ATSR table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarAtsr (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_ATSR_HEADER *Atsr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN AtsrLen;=0D
+=0D
+ if (Atsr =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * Root Port ATS Capability Reporting Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " ATSR address ........................................... 0x%016lx\n=
" :=0D
+ " ATSR address ........................................... 0x%08x\n",=
=0D
+ Atsr=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Atsr->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Atsr->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Atsr->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " ALL_PORTS .......................................... 0x%02x\n",=
=0D
+ Atsr->Flags & EFI_ACPI_DMAR_ATSR_FLAGS_ALL_PORTS=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Atsr->SegmentNumber=0D
+ ));=0D
+=0D
+ AtsrLen =3D Atsr->Header.Length - sizeof(EFI_ACPI_DMAR_ATSR_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Atsr + 1);=0D
+ while (AtsrLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ AtsrLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR RMRR table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Rmrr DMAR RMRR table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarRmrr (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN RmrrLen;=0D
+=0D
+ if (Rmrr =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * Reserved Memory Region Reporting Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " RMRR address ........................................... 0x%016lx\n=
" :=0D
+ " RMRR address ........................................... 0x%08x\n",=
=0D
+ Rmrr=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Rmrr->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Rmrr->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Rmrr->SegmentNumber=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Reserved Memory Region Base Address .................. 0x%016lx\n=
",=0D
+ Rmrr->ReservedMemoryRegionBaseAddress=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Reserved Memory Region Limit Address ................. 0x%016lx\n=
",=0D
+ Rmrr->ReservedMemoryRegionLimitAddress=0D
+ ));=0D
+=0D
+ RmrrLen =3D Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Rmrr + 1);=0D
+ while (RmrrLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ RmrrLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR DRHD table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Drhd DMAR DRHD table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarDrhd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN DrhdLen;=0D
+=0D
+ if (Drhd =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * DMA-Remapping Hardware Definition Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " DRHD address ........................................... 0x%016lx\n=
" :=0D
+ " DRHD address ........................................... 0x%08x\n",=
=0D
+ Drhd=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Drhd->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Drhd->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Drhd->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " INCLUDE_PCI_ALL .................................... 0x%02x\n",=
=0D
+ Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Size ................................................. 0x%02x\n",=
=0D
+ Drhd->Size=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Drhd->SegmentNumber=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Register Base Address ................................ 0x%016lx\n=
",=0D
+ Drhd->RegisterBaseAddress=0D
+ ));=0D
+=0D
+ DrhdLen =3D Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Drhd + 1);=0D
+ while (DrhdLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ DrhdLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump Header of DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmarHeader (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "* DMAR Table =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ "DMAR address ............................................. 0x%016lx\n=
" :=0D
+ "DMAR address ............................................. 0x%08x\n",=
=0D
+ Dmar=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Table Contents:\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Host Address Width ................................... 0x%02x\n",=
=0D
+ Dmar->HostAddressWidth=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Dmar->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " INTR_REMAP ......................................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmar (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ INTN DmarLen;=0D
+=0D
+ if (Dmar =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ VtdLibDumpAcpiDmarHeader (Context, CallbackHandle, Dmar);=0D
+=0D
+ DmarLen =3D Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);=0D
+ while (DmarLen > 0) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdLibDumpDmarDrhd (Context, CallbackHandle, (EFI_ACPI_DMAR_DRHD_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_RMRR:=0D
+ VtdLibDumpDmarRmrr (Context, CallbackHandle, (EFI_ACPI_DMAR_RMRR_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_ATSR:=0D
+ VtdLibDumpDmarAtsr (Context, CallbackHandle, (EFI_ACPI_DMAR_ATSR_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_RHSA:=0D
+ VtdLibDumpDmarRhsa (Context, CallbackHandle, (EFI_ACPI_DMAR_RHSA_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_ANDD:=0D
+ VtdLibDumpDmarAndd (Context, CallbackHandle, (EFI_ACPI_DMAR_ANDD_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_SATC:=0D
+ VtdLibDumpDmarSatc (Context, CallbackHandle, (EFI_ACPI_DMAR_SATC_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_SIDP:=0D
+ VtdLibDumpDmarSidp (Context, CallbackHandle, (EFI_ACPI_DMAR_SIDP_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarLen -=3D DmarHeader->Length;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DRHD DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmarDrhd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ INTN DmarLen;=0D
+=0D
+ if (Dmar =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ VtdLibDumpAcpiDmarHeader (Context, CallbackHandle, Dmar);=0D
+=0D
+ DmarLen =3D Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);=0D
+ while (DmarLen > 0) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdLibDumpDmarDrhd (Context, CallbackHandle, (EFI_ACPI_DMAR_DRHD_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarLen -=3D DmarHeader->Length;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump the PCI device information managed by this VTd engine.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] PciDeviceInfo VTd Unit Information=0D
+**/=0D
+VOID=0D
+VtdLibDumpPciDeviceInfo (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN PCI_DEVICE_INFORMATION *PciDeviceInfo=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+=0D
+ if (PciDeviceInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PCI Device Information (Number 0x%x, Inclu=
deAll - %d):\n",=0D
+ PciDeviceInfo->PciDeviceDataNumber,=0D
+ PciDeviceInfo->IncludeAllFlag=0D
+ ));=0D
+ for (Index =3D 0; Index < PciDeviceInfo->PciDeviceDataNumber; Index++)=
{=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " S%04x B%02x D%02x F%02x\n",=0D
+ PciDeviceInfo->Segment,=0D
+ PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.Bus,=0D
+ PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.Device,=0D
+ PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.Function=0D
+ ));=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR second level paging entry.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in] CallbackHandle Callback handler=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpSecondLevelPagingEntry (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VOID *SecondLevelPagingEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Index1;=0D
+ UINTN Lvl5IndexEnd;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl1PtEntry;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "DMAR Second Level Page Table:\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "SecondLevelPagingEntry Base - 0x%x, Is5Le=
velPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));=0D
+=0D
+ Lvl5IndexEnd =3D Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY) : 1;=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+=0D
+ for (Index5 =3D 0; Index5 < Lvl5IndexEnd; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl5Pt Entry(0x%03x) - 0x%016lx\n=
", Index5, Lvl5PtEntry[Index5].Uint64));=0D
+ }=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_EN=
TRY); Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl4Pt Entry(0x%03x) - 0x%016lx\n=
", Index4, Lvl4PtEntry[Index4].Uint64));=0D
+ }=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_=
ENTRY); Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl3Pt Entry(0x%03x) - 0x%016l=
x\n", Index3, Lvl3PtEntry[Index3].Uint64));=0D
+ }=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ if (Lvl2PtEntry[Index2].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl2Pt Entry(0x%03x) - 0x%0=
16lx\n", Index2, Lvl2PtEntry[Index2].Uint64));=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Bits.PageSize =3D=3D 0) {=0D
+ Lvl1PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64=
BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.A=
ddressHi);=0D
+ for (Index1 =3D 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_P=
AGING_ENTRY); Index1++) {=0D
+ if (Lvl1PtEntry[Index1].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl1Pt Entry(0x%03x) =
- 0x%016lx\n", Index1, Lvl1PtEntry[Index1].Uint64));=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D\n"));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] RootEntry DMAR root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_ROOT_ENTRY *RootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN Index2;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DMAR Context Entry Table:\n"));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "RootEntry Address - 0x%x\n", RootEntry));=0D
+=0D
+ for (Index =3D 0; Index < VTD_ROOT_ENTRY_NUMBER; Index++) {=0D
+ if ((RootEntry[Index].Uint128.Uint64Lo !=3D 0) || (RootEntry[Index].Ui=
nt128.Uint64Hi !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " RootEntry(0x%02x) B%02x - 0x%016lx %01=
6lx\n",=0D
+ Index, Index, RootEntry[Index].Uint128.Uint64Hi, RootEntry[Index].=
Uint128.Uint64Lo));=0D
+ }=0D
+ if (RootEntry[Index].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ ContextEntry =3D (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (Roo=
tEntry[Index].Bits.ContextTablePointerLo, RootEntry[Index].Bits.ContextTabl=
ePointerHi);=0D
+ for (Index2 =3D 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER; Index2++) {=0D
+ if ((ContextEntry[Index2].Uint128.Uint64Lo !=3D 0) || (ContextEntry[=
Index2].Uint128.Uint64Hi !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ContextEntry(0x%02x) D%02xF%02x - =
0x%016lx %016lx\n",=0D
+ Index2, Index2 >> 3, Index2 & 0x7, ContextEntry[Index2].Uint128.=
Uint64Hi, ContextEntry[Index2].Uint128.Uint64Lo));=0D
+ }=0D
+ if (ContextEntry[Index2].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ VtdLibDumpSecondLevelPagingEntry (Context, CallbackHandle, (VOID *) =
(UINTN) VTD_64BITS_ADDRESS (ContextEntry[Index2].Bits.SecondLevelPageTransl=
ationPointerLo, ContextEntry[Index2].Bits.SecondLevelPageTranslationPointer=
Hi), Is5LevelPaging);=0D
+ }=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR extended context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] ExtRootEntry DMAR extended root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarExtContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN Index2;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DMAR ExtContext Entry Table:\n"));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "ExtRootEntry Address - 0x%x\n", ExtRootEntry=
));=0D
+=0D
+ for (Index =3D 0; Index < VTD_ROOT_ENTRY_NUMBER; Index++) {=0D
+ if ((ExtRootEntry[Index].Uint128.Uint64Lo !=3D 0) || (ExtRootEntry[Ind=
ex].Uint128.Uint64Hi !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ExtRootEntry(0x%02x) B%02x - 0x%016lx =
%016lx\n",=0D
+ Index, Index, ExtRootEntry[Index].Uint128.Uint64Hi, ExtRootEntry[I=
ndex].Uint128.Uint64Lo));=0D
+ }=0D
+ if (ExtRootEntry[Index].Bits.LowerPresent =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ ExtContextEntry =3D (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRE=
SS (ExtRootEntry[Index].Bits.LowerContextTablePointerLo, ExtRootEntry[Index=
].Bits.LowerContextTablePointerHi);=0D
+ for (Index2 =3D 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER/2; Index2++) {=0D
+ if ((ExtContextEntry[Index2].Uint256.Uint64_1 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_2 !=3D 0) ||=0D
+ (ExtContextEntry[Index2].Uint256.Uint64_3 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_4 !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ExtContextEntryLower(0x%02x) D%02x=
F%02x - 0x%016lx %016lx %016lx %016lx\n",=0D
+ Index2, Index2 >> 3, Index2 & 0x7, ExtContextEntry[Index2].Uint2=
56.Uint64_4, ExtContextEntry[Index2].Uint256.Uint64_3, ExtContextEntry[Inde=
x2].Uint256.Uint64_2, ExtContextEntry[Index2].Uint256.Uint64_1));=0D
+ }=0D
+ if (ExtContextEntry[Index2].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ VtdLibDumpSecondLevelPagingEntry (Context, CallbackHandle, (VOID *) =
(UINTN) VTD_64BITS_ADDRESS (ExtContextEntry[Index2].Bits.SecondLevelPageTra=
nslationPointerLo, ExtContextEntry[Index2].Bits.SecondLevelPageTranslationP=
ointerHi), Is5LevelPaging);=0D
+ }=0D
+=0D
+ if (ExtRootEntry[Index].Bits.UpperPresent =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ ExtContextEntry =3D (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRE=
SS (ExtRootEntry[Index].Bits.UpperContextTablePointerLo, ExtRootEntry[Index=
].Bits.UpperContextTablePointerHi);=0D
+ for (Index2 =3D 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER/2; Index2++) {=0D
+ if ((ExtContextEntry[Index2].Uint256.Uint64_1 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_2 !=3D 0) ||=0D
+ (ExtContextEntry[Index2].Uint256.Uint64_3 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_4 !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ExtContextEntryUpper(0x%02x) D%02x=
F%02x - 0x%016lx %016lx %016lx %016lx\n",=0D
+ Index2, (Index2 + 128) >> 3, (Index2 + 128) & 0x7, ExtContextEnt=
ry[Index2].Uint256.Uint64_4, ExtContextEntry[Index2].Uint256.Uint64_3, ExtC=
ontextEntry[Index2].Uint256.Uint64_2, ExtContextEntry[Index2].Uint256.Uint6=
4_1));=0D
+ }=0D
+ if (ExtContextEntry[Index2].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ }=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd FRCD register.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] FrcdRegNum FRCD Register Number=0D
+ @param[in] FrcdRegTab FRCD Register Table=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdFrcdRegs (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN UINT16 FrcdRegNum,=0D
+ IN VTD_UINT128 *FrcdRegTab=0D
+ )=0D
+{=0D
+ UINT16 Index;=0D
+ VTD_FRCD_REG FrcdReg;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ for (Index =3D 0; Index < FrcdRegNum; Index++) {=0D
+ FrcdReg.Uint64[0] =3D FrcdRegTab[Index].Uint64Lo;=0D
+ FrcdReg.Uint64[1] =3D FrcdRegTab[Index].Uint64Hi;=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FRCD_REG[%d] - 0x%016lx %016lx\n", Index=
, FrcdReg.Uint64[1], FrcdReg.Uint64[0]));=0D
+ if (FrcdReg.Uint64[1] !=3D 0 || FrcdReg.Uint64[0] !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Fault Info - 0x%016lx\n", VTD_64BITS=
_ADDRESS(FrcdReg.Bits.FILo, FrcdReg.Bits.FIHi)));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Fault Bit - %d\n", FrcdReg.Bits.F));=
=0D
+ SourceId.Uint16 =3D (UINT16)FrcdReg.Bits.SID;=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Source - B%02x D%02x F%02x\n", Sourc=
eId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Type - 0x%02x\n", (FrcdReg.Bits.T1 <=
< 1) | FrcdReg.Bits.T2));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Reason - %x (Refer to VTd Spec, Appe=
ndix A)\n", FrcdReg.Bits.FR));=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsAll (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_INFO *VtdRegInfo=0D
+ )=0D
+{=0D
+ if (VtdRegInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "VTd Engine: [0x%016lx]\n", VtdRegInfo->Bas=
eAddress));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " VER_REG - 0x%08x\n", VtdRegInfo->V=
erReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " CAP_REG - 0x%016lx\n", VtdRegInfo->C=
apReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ECAP_REG - 0x%016lx\n", VtdRegInfo->E=
capReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " GSTS_REG - 0x%08x \n", VtdRegInfo->G=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", VtdRegInfo->R=
taddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " CCMD_REG - 0x%016lx\n", VtdRegInfo->C=
cmdReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FSTS_REG - 0x%08x\n", VtdRegInfo->F=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FECTL_REG - 0x%08x\n", VtdRegInfo->F=
ectlReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FEDATA_REG - 0x%08x\n", VtdRegInfo->F=
edataReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FEADDR_REG - 0x%08x\n", VtdRegInfo->F=
eaddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FEUADDR_REG - 0x%08x\n", VtdRegInfo->F=
euaddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IQERCD_REG - 0x%016lx\n", VtdRegInfo->I=
qercdReg));=0D
+=0D
+ VtdLibDumpVtdFrcdRegs (Context, CallbackHandle, VtdRegInfo->FrcdRegNum=
, VtdRegInfo->FrcdReg);=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IVA_REG - 0x%016lx\n", VtdRegInfo->I=
vaReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IOTLB_REG - 0x%016lx\n", VtdRegInfo->I=
otlbReg));=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsThin (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_THIN_INFO *VtdRegInfo=0D
+ )=0D
+{=0D
+ if (VtdRegInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "VTd Engine: [0x%016lx]\n", VtdRegInfo->Bas=
eAddress));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " GSTS_REG - 0x%08x \n", VtdRegInfo->G=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", VtdRegInfo->R=
taddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FSTS_REG - 0x%08x\n", VtdRegInfo->F=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FECTL_REG - 0x%08x\n", VtdRegInfo->F=
ectlReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IQERCD_REG - 0x%016lx\n", VtdRegInfo->I=
qercdReg));=0D
+=0D
+ VtdLibDumpVtdFrcdRegs (Context, CallbackHandle, VtdRegInfo->FrcdRegNum=
, VtdRegInfo->FrcdReg);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsQi (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_QI_INFO *VtdRegInfo=0D
+ )=0D
+{=0D
+ if (VtdRegInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "VTd Engine: [0x%016lx]\n", VtdRegInfo->Bas=
eAddress));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FSTS_REG - 0x%08x\n", VtdRegInfo->F=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IQERCD_REG - 0x%016lx\n", VtdRegInfo->I=
qercdReg));=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd PEI pre-mem event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_2PARAM event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpPeiPreMemInfo (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_2PARAM *Event=0D
+ )=0D
+{=0D
+ UINT64 VtdBarAddress;=0D
+ UINT64 Mode;=0D
+ UINT64 Status;=0D
+=0D
+ VtdBarAddress =3D Event->Data1;=0D
+ Mode =3D Event->Data2 & 0xFF;=0D
+ Status =3D (Event->Data2>>8) & 0xFF;=0D
+=0D
+ switch (Mode) {=0D
+ case VTD_LOG_PEI_PRE_MEM_DISABLE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Disabled [0x%016lx] 0x%x=
\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_ADM:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Enable Abort DMA Mode [0=
x%016lx] 0x%x\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_TE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Enable NULL Root Entry T=
able [0x%016lx] 0x%x\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_PMR:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Enable PMR [0x%016lx] 0x=
%x\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_NOT_USED:=0D
+ //=0D
+ // Not used=0D
+ //=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Unknown [0x%016lx] 0x%x\=
n", VtdBarAddress, Status));=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd Queued Invaildation event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_2PARAM event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpQueuedInvaildation (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_2PARAM *Event=0D
+ )=0D
+{=0D
+ switch (Event->Data1) {=0D
+ case VTD_LOG_QI_DISABLE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] Disable\n", Event->Data2));=0D
+ break;=0D
+ case VTD_LOG_QI_ENABLE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] Enable\n", Event->Data2));=0D
+ break;=0D
+ case VTD_LOG_QI_ERROR_OUT_OF_RESOURCES:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] error - Out of resources\n", E=
vent->Data2));=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] error - (0x%x)\n", Event->Data=
2, Event->Data1));=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd registers event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_CONTEXT event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpRegisters (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_CONTEXT *Event=0D
+ )=0D
+{=0D
+ switch (Event->Param) {=0D
+ case VTDLOG_REGISTER_ALL:=0D
+ VtdLibDumpVtdRegsAll (Context, CallbackHandle, (VTD_REGESTER_INFO *) E=
vent->Data);=0D
+ break;=0D
+ case VTDLOG_REGISTER_THIN:=0D
+ VtdLibDumpVtdRegsThin (Context, CallbackHandle, (VTD_REGESTER_THIN_INF=
O *) Event->Data);=0D
+ break;=0D
+ case VTDLOG_REGISTER_QI:=0D
+ VtdLibDumpVtdRegsQi (Context, CallbackHandle, (VTD_REGESTER_QI_INFO *)=
Event->Data);=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Unknown format (%d)\n", Event->Param));=
=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd PEI Error event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_2PARAM event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpPeiError (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_2PARAM *Event=0D
+ )=0D
+{=0D
+ UINT64 Timestamp;=0D
+=0D
+ Timestamp =3D Event->Header.Timestamp;=0D
+=0D
+ switch (Event->Data1) {=0D
+ case VTD_LOG_PEI_VTD_ERROR_PPI_ALLOC:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Error - PPI alloc length [0x%01=
6lx]\n", Timestamp, Event->Data2));=0D
+ break;=0D
+ case VTD_LOG_PEI_VTD_ERROR_PPI_MAP:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Error - PPI map length [0x%016l=
x]\n", Timestamp, Event->Data2));=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Error - Unknown (%d) 0x%x\n", T=
imestamp, Event->Data1, Event->Data2));=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd registers event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_CONTEXT event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpSetAttribute (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_CONTEXT *Event=0D
+ )=0D
+{=0D
+ VTD_PROTOCOL_SET_ATTRIBUTE * SetAttributeInfo;=0D
+=0D
+ SetAttributeInfo =3D (VTD_PROTOCOL_SET_ATTRIBUTE *) Event->Data;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: SetAttribute SourceId =3D 0x%04x,=
Address =3D 0x%lx, Length =3D 0x%lx, IoMmuAccess =3D 0x%lx, %r\n", =0D
+ Event->Header.Timestamp,=0D
+ SetAttributeInfo->SourceId.Uint16,=0D
+ SetAttributeInfo->DeviceAddress,=0D
+ SetAttributeInfo->Length,=0D
+ SetAttributeInfo->Status));=0D
+}=0D
+=0D
+=0D
+=0D
+/**=0D
+ Dump Vtd Root Table event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_CONTEXT event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpRootTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_CONTEXT *Event=0D
+ )=0D
+{=0D
+ VTD_ROOT_TABLE_INFO *RootTableInfo;=0D
+=0D
+ RootTableInfo =3D (VTD_ROOT_TABLE_INFO *) Event->Data;=0D
+ if (Event->Param =3D=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Root Entry Table [0x%016lx]\n",=
Event->Header.Timestamp, RootTableInfo->BaseAddress));=0D
+ VtdLibDumpDmarContextEntryTable (Context, CallbackHandle, (VTD_ROOT_EN=
TRY *) (UINTN) RootTableInfo->TableAddress, RootTableInfo->Is5LevelPaging);=
=0D
+=0D
+ } else if (Event->Param =3D=3D 1) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Ext Root Entry Table [0x%016lx]=
\n", Event->Header.Timestamp, RootTableInfo->BaseAddress));=0D
+ VtdLibDumpDmarExtContextEntryTable (Context, CallbackHandle, (VTD_EXT_=
ROOT_ENTRY *) (UINTN) RootTableInfo->TableAddress, RootTableInfo->Is5Level=
Paging);=0D
+=0D
+ } else {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Unknown Root Table Type (%d)\n"=
, Event->Header.Timestamp, Event->Param));=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Decode log event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] PciDeviceId Callback handler=0D
+ @param[in] Event Event struct=0D
+=0D
+ @retval TRUE Decode event success=0D
+ @retval FALSE Unknown event=0D
+**/=0D
+BOOLEAN=0D
+VtdLibDecodeEvent (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT *Event=0D
+ )=0D
+{=0D
+ BOOLEAN Result;=0D
+ UINT64 Timestamp;=0D
+ UINT64 Data1;=0D
+ UINT64 Data2;=0D
+=0D
+ Result =3D TRUE;=0D
+ Timestamp =3D Event->EventHeader.Timestamp;=0D
+ Data1 =3D Event->CommenEvent.Data1;=0D
+ Data2 =3D Event->CommenEvent.Data2;=0D
+=0D
+ switch (Event->EventHeader.LogType) {=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_BASIC):=0D
+ if (Data1 & VTD_LOG_ERROR_BUFFER_FULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Info : Log Buffer Full\n", Ti=
mestamp));=0D
+ Data1 &=3D ~VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ if (Data1 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Info : 0x%x, 0x%x\n", Timesta=
mp, Data1, Data2));=0D
+ }=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PRE_MEM_DMA_PROTECT):=0D
+ VtdLibDumpPeiPreMemInfo (Context, CallbackHandle, &(Event->CommenEvent=
));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PMR_LOW_MEMORY_RANGE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PMR Low Memory Range [0x%x, 0x%=
x]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PMR_HIGH_MEMORY_RANGE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PMR High Memory Range [0x%016lx=
, 0x%016lx]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PROTECT_MEMORY_RANGE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Protected DMA Memory Range [0x%=
016lx, 0x%016lx]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_POST_MEM_ENABLE_DMA_PROTECT):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Enable DMA protection [0x%016lx=
] %r\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_POST_MEM_DISABLE_DMA_PROTECT):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Disable DMA protection [0x%016l=
x]\n", Timestamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_QUEUED_INVALIDATION):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Queued Invalidation", Timestamp=
));=0D
+ VtdLibDumpQueuedInvaildation (Context, CallbackHandle, &(Event->Commen=
Event));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_REGISTER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Dump Registers\n", Timestamp));=
=0D
+ VtdLibDumpRegisters (Context, CallbackHandle, &(Event->ContextEvent));=
=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_VTD_ERROR):=0D
+ VtdLibDumpPeiError (Context, CallbackHandle, &(Event->CommenEvent));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PPI_ALLOC_BUFFER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PPI AllocateBuffer 0x%x, Length=
=3D 0x%x\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PPI_MAP):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PPI Map 0x%x, Length =3D 0x%x\n=
", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_BASIC):=0D
+ if (Data1 & VTD_LOG_ERROR_BUFFER_FULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Info : Log Buffer Full\n", Ti=
mestamp));=0D
+ Data1 &=3D ~VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ if (Data1 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Info : 0x%x, 0x%x\n", Timesta=
mp, Data1, Data2));=0D
+ }=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_DMAR_TABLE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: DMAR Table\n", Timestamp));=0D
+ VtdLibDumpAcpiDmar (Context, CallbackHandle, (EFI_ACPI_DMAR_HEADER *) =
Event->ContextEvent.Data);=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_SETUP_VTD):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Setup VTd Below/Above 4G Memory=
Limit =3D [0x%016lx, 0x%016lx]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_PCI_DEVICE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: PCI Devices [0x%016lx]\n", Time=
stamp, Event->ContextEvent.Param));=0D
+ VtdLibDumpPciDeviceInfo (Context, CallbackHandle, (PCI_DEVICE_INFORMAT=
ION *) Event->ContextEvent.Data);=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_REGISTER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Dump Registers\n", Timestamp));=
=0D
+ VtdLibDumpRegisters (Context, CallbackHandle, &(Event->ContextEvent));=
=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_ENABLE_DMAR):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Enable DMAR [0x%016lx]\n", Time=
stamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_DISABLE_DMAR):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Disable DMAR [0x%016lx]\n", Tim=
estamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_DISABLE_PMR):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Disable PMR [0x%016lx] %r\n", T=
imestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Install IOMMU Protocol %r\n", T=
imestamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_QUEUED_INVALIDATION):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Queued Invalidation", Timestamp=
));=0D
+ VtdLibDumpQueuedInvaildation (Context, CallbackHandle, &(Event->Commen=
Event));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_ROOT_TABLE):=0D
+ VtdLibDumpRootTable (Context, CallbackHandle, &(Event->ContextEvent));=
=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_ALLOC_BUFFER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: AllocateBuffer 0x%x, Page =3D 0=
x%x\n", Timestamp, Data2, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_FREE_BUFFER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: FreeBuffer 0x%x, Page =3D 0x%x\=
n", Timestamp, Data2, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_MAP):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Map 0x%x, Operation =3D 0x%x\n"=
, Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_UNMAP):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Unmap 0x%x, NumberOfBytes =3D 0=
x%x\n", Timestamp, Data2, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_SET_ATTRIBUTE):=0D
+ VtdLibDumpSetAttribute (Context, CallbackHandle, &(Event->ContextEvent=
));=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "## Unknown VTd Event Type=3D%d Timestamp=
=3D%ld Size=3D%d\n", Event->EventHeader.LogType, Event->EventHeader.Timesta=
mp, Event->EventHeader.DataSize));=0D
+ Result =3D FALSE;=0D
+ break;=0D
+ }=0D
+=0D
+ return Result;=0D
+}=0D
+=0D
+/**=0D
+ Flush VTd engine write buffer.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibFlushWriteBuffer (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_CAP_REG CapReg;=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+=0D
+ if (CapReg.Bits.RWBF !=3D 0) {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);=
=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_WBF) !=3D 0);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Clear Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask=0D
+**/=0D
+VOID=0D
+VtdLibClearGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ UINT32 Status;=0D
+ UINT32 Command;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Status =3D (Reg32 & 0x96FFFFFF); // Reset the one-shot bits=0D
+ Command =3D (Status & (~BitMask));=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));=0D
+=0D
+ //=0D
+ // Poll on Status bit of Global status register to become zero=0D
+ //=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & BitMask) =3D=3D BitMask);=0D
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));=0D
+}=0D
+=0D
+/**=0D
+ Set Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask=0D
+**/=0D
+VOID=0D
+VtdLibSetGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ UINT32 Status;=0D
+ UINT32 Command;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Status =3D (Reg32 & 0x96FFFFFF); // Reset the one-shot bits=0D
+ Command =3D (Status | BitMask);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));=0D
+=0D
+ //=0D
+ // Poll on Status bit of Global status register to become not zero=0D
+ //=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & BitMask) =3D=3D 0);=0D
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));=0D
+}=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisableDmar (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+=0D
+ DEBUG ((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x]\n", VtdUnitBase=
Address));=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Disable Dmar=0D
+ //=0D
+ //=0D
+ // Set TE (Translation Enable: BIT31) of Global command register to zero=
=0D
+ //=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ //=0D
+ // Set SRTP (Set Root Table Pointer: BIT30) of Global command register i=
n order to update the root table pointerDisable VTd=0D
+ //=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP)=
;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ DEBUG ((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));=0D
+=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, 0);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD () Disabled!<<<<<<\n"));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable PMR.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS PMR is disabled.=0D
+ @retval EFI_UNSUPPORTED PMR is not supported.=0D
+ @retval EFI_NOT_STARTED PMR was not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisablePmr (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_CAP_REG CapReg;=0D
+ EFI_STATUS Status;=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+ if (CapReg.Bits.PLMR =3D=3D 0 || CapReg.Bits.PHMR =3D=3D 0) {=0D
+ //=0D
+ // PMR is not supported=0D
+ //=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);=0D
+ if ((Reg32 & BIT0) !=3D 0) {=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);=0D
+ } while((Reg32 & BIT0) !=3D 0);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Pmr [0x%016lx] disabled\n", VtdUnitBaseAddress));=
=0D
+ Status =3D EFI_SUCCESS;=0D
+ } else {=0D
+ DEBUG ((DEBUG_INFO,"Pmr [0x%016lx] not enabled\n", VtdUnitBaseAddress)=
);=0D
+ Status =3D EFI_NOT_STARTED;=0D
+ }=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Disable queued invalidation interface.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibDisableQueuedInvalidationInterface (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ QiDesc.Uint64[0] =3D QI_IWD_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress, &QiDesc, T=
RUE);=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 &=3D (~B_GMCD_REG_QIE);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. [%x] GCMD_RE=
G =3D 0x%x\n", VtdUnitBaseAddress, Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) !=3D 0);=0D
+=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, 0);=0D
+}=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Base The base address of memory to be flush=
ed.=0D
+ @param[in] Size The size of memory in bytes to be flus=
hed.=0D
+**/=0D
+VOID=0D
+VtdLibFlushPageTableMemory (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ VTD_ECAP_REG ECapReg;=0D
+=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);=0D
+ if (ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *)Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+ @param[in] ClearFaultBits Clear Error bits=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+ @retval EFI_NOT_READY Queued invalidation is not inited.=0D
+ @retval EFI_DEVICE_ERROR Detect fault, need to clear fault bits=
if ClearFaultBits is FALSE=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibSubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN VOID *Desc,=0D
+ IN BOOLEAN ClearFaultBits=0D
+ )=0D
+{=0D
+ UINTN QueueSize;=0D
+ UINTN QueueTail;=0D
+ UINTN QueueHead;=0D
+ QI_DESC *Qi128Desc;=0D
+ QI_256_DESC *Qi256Desc;=0D
+ VTD_IQA_REG IqaReg;=0D
+ VTD_IQT_REG IqtReg;=0D
+ VTD_IQH_REG IqhReg;=0D
+ UINT32 FaultReg;=0D
+ UINT64 IqercdReg;=0D
+=0D
+ if (Desc =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ if (IqaReg.Bits.IQA =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"Invalidation Queue Buffer not ready [0x%lx]\n", I=
qaReg.Uint64));=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ IqtReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQT_REG);=0D
+=0D
+ if (IqaReg.Bits.DW =3D=3D 0) {=0D
+ //=0D
+ // 128-bit descriptor=0D
+ //=0D
+ QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 8));=0D
+ Qi128Desc =3D (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);=
=0D
+ QueueTail =3D (UINTN) IqtReg.Bits128Desc.QT;=0D
+ Qi128Desc +=3D QueueTail;=0D
+ CopyMem (Qi128Desc, Desc, sizeof (QI_DESC));=0D
+ VtdLibFlushPageTableMemory (VtdUnitBaseAddress, (UINTN) Qi128Desc, siz=
eof(QI_DESC));=0D
+ QueueTail =3D (QueueTail + 1) % QueueSize;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x=
%016lx]\n",=0D
+ VtdUnitBaseAddress,=0D
+ QueueTail,=0D
+ Qi128Desc->Low,=0D
+ Qi128Desc->High));=0D
+=0D
+ IqtReg.Bits128Desc.QT =3D QueueTail;=0D
+ } else {=0D
+ //=0D
+ // 256-bit descriptor=0D
+ //=0D
+ QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 7));=0D
+ Qi256Desc =3D (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHI=
FT);=0D
+ QueueTail =3D (UINTN) IqtReg.Bits256Desc.QT;=0D
+ Qi256Desc +=3D QueueTail;=0D
+ CopyMem (Qi256Desc, Desc, sizeof (QI_256_DESC));=0D
+ VtdLibFlushPageTableMemory (VtdUnitBaseAddress, (UINTN) Qi256Desc, siz=
eof(QI_256_DESC));=0D
+ QueueTail =3D (QueueTail + 1) % QueueSize;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x=
%016lx, 0x%016lx, 0x%016lx]\n",=0D
+ VtdUnitBaseAddress,=0D
+ QueueTail,=0D
+ Qi256Desc->Uint64[0],=0D
+ Qi256Desc->Uint64[1],=0D
+ Qi256Desc->Uint64[2],=0D
+ Qi256Desc->Uint64[3]));=0D
+=0D
+ IqtReg.Bits256Desc.QT =3D QueueTail;=0D
+ }=0D
+=0D
+ //=0D
+ // Update the HW tail register indicating the presence of new descriptor=
s.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64);=0D
+=0D
+ do {=0D
+ FaultReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG);=0D
+ if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {=0D
+ IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_REG);=0D
+ DEBUG((DEBUG_ERROR, "BAR [0x%016lx] Detect Queue Invalidation Fault =
[0x%08x] - IQERCD [0x%016lx]\n", VtdUnitBaseAddress, FaultReg, IqercdReg));=
=0D
+ if (ClearFaultBits) {=0D
+ FaultReg &=3D (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);=
=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, FaultReg);=0D
+ }=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ IqhReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQH_REG);=0D
+ if (IqaReg.Bits.DW =3D=3D 0) {=0D
+ QueueHead =3D (UINTN) IqhReg.Bits128Desc.QH;=0D
+ } else {=0D
+ QueueHead =3D (UINTN) IqhReg.Bits256Desc.QH;=0D
+ }=0D
+ } while (QueueTail !=3D QueueHead);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelV=
TdPeiDxeLib.inf b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/I=
ntelVTdPeiDxeLib.inf
new file mode 100644
index 000000000..0d6dff5fa
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiDx=
eLib.inf
@@ -0,0 +1,30 @@
+### @file=0D
+# Component information file for Intel VTd function library.=0D
+#=0D
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+#=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+###=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdPeiDxeLib=0D
+ FILE_GUID =3D 6cd8b1ea-152d-4cc9-b9b1-f5c692ba63da=
=0D
+ VERSION_STRING =3D 1.0=0D
+ MODULE_TYPE =3D BASE=0D
+ LIBRARY_CLASS =3D IntelVTdPeiDxeLib=0D
+=0D
+[LibraryClasses]=0D
+ BaseLib=0D
+ PrintLib=0D
+ IoLib=0D
+ CacheMaintenanceLib=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[Sources]=0D
+ IntelVTdPeiDxeLib.c=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelV=
TdPeiDxeLibExt.inf b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLi=
b/IntelVTdPeiDxeLibExt.inf
new file mode 100644
index 000000000..9a2b28e12
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiDx=
eLibExt.inf
@@ -0,0 +1,34 @@
+### @file=0D
+# Component information file for Intel VTd function library.=0D
+#=0D
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+#=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+###=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdPeiDxeLib=0D
+ FILE_GUID =3D 6fd8b3aa-852d-6ccA-b9b2-f5c692ba63ca=
=0D
+ VERSION_STRING =3D 1.0=0D
+ MODULE_TYPE =3D BASE=0D
+ LIBRARY_CLASS =3D IntelVTdPeiDxeLib=0D
+=0D
+[LibraryClasses]=0D
+ BaseLib=0D
+ PrintLib=0D
+ IoLib=0D
+ CacheMaintenanceLib=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[Sources]=0D
+ IntelVTdPeiDxeLib.c=0D
+=0D
+[BuildOptions]=0D
+ *_*_X64_CC_FLAGS =3D -DEXT_CALLBACK=0D
+=0D
--=20
2.26.2.windows.1
for pre-boot DMA protection feature.
Signed-off-by: Sheng Wei <w.sheng@...>
Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Jenny Huang <jenny.huang@...>
Cc: Robert Kowalewski <robert.kowalewski@...>
---
.../Feature/VTd/IntelVTdCoreDxe/BmDma.c | 547 +++++
.../VTd/IntelVTdCoreDxe/DmaProtection.c | 703 +++++++
.../VTd/IntelVTdCoreDxe/DmaProtection.h | 658 ++++++
.../VTd/IntelVTdCoreDxe/DmarAcpiTable.c | 398 ++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.c | 787 +++++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.inf | 92 +
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.uni | 14 +
.../IntelVTdCoreDxe/IntelVTdCoreDxeExtra.uni | 14 +
.../Feature/VTd/IntelVTdCoreDxe/PciInfo.c | 419 ++++
.../VTd/IntelVTdCoreDxe/TranslationTable.c | 1112 ++++++++++
.../VTd/IntelVTdCoreDxe/TranslationTableEx.c | 108 +
.../Feature/VTd/IntelVTdCoreDxe/VtdReg.c | 757 +++++++
.../Feature/VTd/IntelVTdCorePei/DmarTable.c | 301 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.c | 1099 ++++++++++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.h | 272 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.inf | 70 +
.../VTd/IntelVTdCorePei/IntelVTdCorePei.uni | 14 +
.../IntelVTdCorePei/IntelVTdCorePeiExtra.uni | 14 +
.../VTd/IntelVTdCorePei/IntelVTdDmar.c | 727 +++++++
.../VTd/IntelVTdCorePei/TranslationTable.c | 926 +++++++++
.../Include/Guid/VtdLogDataHob.h | 151 ++
.../Include/Library/IntelVTdPeiDxeLib.h | 329 +++
.../IntelSiliconPkg/Include/Protocol/VtdLog.h | 59 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 21 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dsc | 1 +
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.c | 1819 +++++++++++++++++
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.inf | 30 +
.../IntelVTdPeiDxeLibExt.inf | 34 +
28 files changed, 11476 insertions(+)
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/BmDma.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmarAcpiTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxeExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/PciInfo.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTableEx.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/VtdReg.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/DmarTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePeiExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdDmar.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHo=
b.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdP=
eiDxeLib.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLibExt.inf
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDm=
a.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
new file mode 100644
index 000000000..41917a004
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
@@ -0,0 +1,547 @@
+/** @file=0D
+ BmDma related function=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+// TBD: May make it a policy=0D
+#define DMA_MEMORY_TOP MAX_UINTN=0D
+//#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL=0D
+=0D
+#define MAP_HANDLE_INFO_SIGNATURE SIGNATURE_32 ('H', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EFI_HANDLE DeviceHandle;=0D
+ UINT64 IoMmuAccess;=0D
+} MAP_HANDLE_INFO;=0D
+#define MAP_HANDLE_INFO_FROM_LINK(a) CR (a, MAP_HANDLE_INFO, Link, MAP_HAN=
DLE_INFO_SIGNATURE)=0D
+=0D
+#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EDKII_IOMMU_OPERATION Operation;=0D
+ UINTN NumberOfBytes;=0D
+ UINTN NumberOfPages;=0D
+ EFI_PHYSICAL_ADDRESS HostAddress;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ LIST_ENTRY HandleList;=0D
+} MAP_INFO;=0D
+#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)=0D
+=0D
+LIST_ENTRY gMaps =3D INITIALIZE_LIST_HEAD_VARIABLE(=
gMaps);=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ //=0D
+ // Find MapInfo according to DeviceAddress=0D
+ //=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo->DeviceAddress =3D=3D DeviceAddress) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapInfo =3D=3D NULL) || (MapInfo->DeviceAddress !=3D DeviceAddress)=
) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: DeviceAddress(0x%lx) =
- not found\n", DeviceAddress));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // Find MapHandleInfo according to DeviceHandle=0D
+ //=0D
+ MapHandleInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&MapInfo->HandleList)=0D
+ ; !IsNull (&MapInfo->HandleList, Link)=0D
+ ; Link =3D GetNextNode (&MapInfo->HandleList, Link)=0D
+ ) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (Link);=0D
+ if (MapHandleInfo->DeviceHandle =3D=3D DeviceHandle) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapHandleInfo !=3D NULL) && (MapHandleInfo->DeviceHandle =3D=3D Dev=
iceHandle)) {=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // No DeviceHandle=0D
+ // Initialize and insert the MAP_HANDLE_INFO structure=0D
+ //=0D
+ MapHandleInfo =3D AllocatePool (sizeof (MAP_HANDLE_INFO));=0D
+ if (MapHandleInfo =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: %r\n", EFI_OUT_OF_RES=
OURCES));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ MapHandleInfo->Signature =3D MAP_HANDLE_INFO_SIGNATURE;=0D
+ MapHandleInfo->DeviceHandle =3D DeviceHandle;=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ InsertTailList (&MapInfo->HandleList, &MapHandleInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+ MAP_INFO *MapInfo;=0D
+ EFI_PHYSICAL_ADDRESS DmaMemoryTop;=0D
+ BOOLEAN NeedRemap;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ if (NumberOfBytes =3D=3D NULL || DeviceAddress =3D=3D NULL ||=0D
+ Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: =3D=3D> 0x%08x - 0x%08x (%x)\n", HostA=
ddress, *NumberOfBytes, Operation));=0D
+=0D
+ //=0D
+ // Make sure that Operation is valid=0D
+ //=0D
+ if ((UINT32) Operation >=3D EdkiiIoMmuOperationMaximum) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ NeedRemap =3D FALSE;=0D
+ PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;=0D
+=0D
+ DmaMemoryTop =3D DMA_MEMORY_TOP;=0D
+=0D
+ //=0D
+ // Alignment check=0D
+ //=0D
+ if ((*NumberOfBytes !=3D ALIGN_VALUE(*NumberOfBytes, SIZE_4KB)) ||=0D
+ (PhysicalAddress !=3D ALIGN_VALUE(PhysicalAddress, SIZE_4KB))) {=0D
+ if ((Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer) ||=0D
+ (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) {=0D
+ //=0D
+ // The input buffer might be a subset from IoMmuAllocateBuffer.=0D
+ // Skip the check.=0D
+ //=0D
+ } else {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+ }=0D
+=0D
+ if ((PhysicalAddress + *NumberOfBytes) >=3D DMA_MEMORY_TOP) {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+=0D
+ if (((Operation !=3D EdkiiIoMmuOperationBusMasterRead64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterWrite64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) &&=0D
+ ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {=0D
+ //=0D
+ // If the root bridge or the device cannot handle performing DMA above=
=0D
+ // 4GB but any part of the DMA transfer being mapped is above 4GB, the=
n=0D
+ // map the DMA transfer to a buffer below 4GB.=0D
+ //=0D
+ NeedRemap =3D TRUE;=0D
+ DmaMemoryTop =3D MIN (DmaMemoryTop, SIZE_4GB - 1);=0D
+ }=0D
+=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64) {=0D
+ if (NeedRemap) {=0D
+ //=0D
+ // Common Buffer operations can not be remapped. If the common buff=
er=0D
+ // is above 4GB, then it is not possible to generate a mapping, so r=
eturn=0D
+ // an error.=0D
+ //=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is=
=0D
+ // called later.=0D
+ //=0D
+ MapInfo =3D AllocatePool (sizeof (MAP_INFO));=0D
+ if (MapInfo =3D=3D NULL) {=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_OUT_OF_RESOURCES));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the MAP_INFO structure=0D
+ //=0D
+ MapInfo->Signature =3D MAP_INFO_SIGNATURE;=0D
+ MapInfo->Operation =3D Operation;=0D
+ MapInfo->NumberOfBytes =3D *NumberOfBytes;=0D
+ MapInfo->NumberOfPages =3D EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes=
);=0D
+ MapInfo->HostAddress =3D PhysicalAddress;=0D
+ MapInfo->DeviceAddress =3D DmaMemoryTop;=0D
+ InitializeListHead(&MapInfo->HandleList);=0D
+=0D
+ //=0D
+ // Allocate a buffer below 4GB to map the transfer to.=0D
+ //=0D
+ if (NeedRemap) {=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ EfiBootServicesData,=0D
+ MapInfo->NumberOfPages,=0D
+ &MapInfo->DeviceAddress=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (MapInfo);=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+=0D
+ //=0D
+ // If this is a read operation from the Bus Master's point of view,=0D
+ // then copy the contents of the real buffer into the mapped buffer=0D
+ // so the Bus Master can read the contents of the real buffer.=0D
+ //=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterRead ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterRead64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+ } else {=0D
+ MapInfo->DeviceAddress =3D MapInfo->HostAddress;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ InsertTailList (&gMaps, &MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // The DeviceAddress is the address of the maped buffer below 4GB=0D
+ //=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ //=0D
+ // Return a pointer to the MAP_INFO structure in Mapping=0D
+ //=0D
+ *Mapping =3D MapInfo;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: 0x%08x - 0x%08x <=3D=3D\n", *DeviceAdd=
ress, *Mapping));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_MAP, (UINT64) (*DeviceAddress), (UINT64=
) Operation);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuUnmap: 0x%08x\n", Mapping));=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ RemoveEntryList (&MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // remove all nodes in MapInfo->HandleList=0D
+ //=0D
+ while (!IsListEmpty (&MapInfo->HandleList)) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (MapInfo->HandleList.Forwa=
rdLink);=0D
+ RemoveEntryList (&MapHandleInfo->Link);=0D
+ FreePool (MapHandleInfo);=0D
+ }=0D
+=0D
+ if (MapInfo->DeviceAddress !=3D MapInfo->HostAddress) {=0D
+ //=0D
+ // If this is a write operation from the Bus Master's point of view,=0D
+ // then copy the contents of the mapped buffer into the real buffer=0D
+ // so the processor can read the contents of the real buffer.=0D
+ //=0D
+ if (MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite ||=0D
+ MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ //=0D
+ // Free the mapped buffer and the MAP_INFO structure.=0D
+ //=0D
+ gBS->FreePages (MapInfo->DeviceAddress, MapInfo->NumberOfPages);=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_UNMAP, MapInfo->NumberOfBytes, MapInfo-=
DeviceAddress);=0D+=0D
+ FreePool (Mapping);=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: =3D=3D> 0x%08x\n", Pages));=
=0D
+=0D
+ //=0D
+ // Validate Attributes=0D
+ //=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) !=
=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ //=0D
+ // Check for invalid inputs=0D
+ //=0D
+ if (HostAddress =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ //=0D
+ // The only valid memory types are EfiBootServicesData and=0D
+ // EfiRuntimeServicesData=0D
+ //=0D
+ if (MemoryType !=3D EfiBootServicesData &&=0D
+ MemoryType !=3D EfiRuntimeServicesData) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ PhysicalAddress =3D DMA_MEMORY_TOP;=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) =3D=3D 0) {=
=0D
+ //=0D
+ // Limit allocations to memory below 4GB=0D
+ //=0D
+ PhysicalAddress =3D MIN (PhysicalAddress, SIZE_4GB - 1);=0D
+ }=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ MemoryType,=0D
+ Pages,=0D
+ &PhysicalAddress=0D
+ );=0D
+ if (!EFI_ERROR (Status)) {=0D
+ *HostAddress =3D (VOID *) (UINTN) PhysicalAddress;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_ALLOC_BUFFER, (UINT64) Pages, (UINT64=
) (*HostAddress));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: 0x%08x <=3D=3D\n", *HostAdd=
ress));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuFreeBuffer: 0x%\n", Pages));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_FREE_BUFFER, Pages, (UINT64) HostAddres=
s);=0D
+=0D
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages=
);=0D
+}=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ LIST_ENTRY *Link;=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ *NumberOfPages =3D MapInfo->NumberOfPages;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.c
new file mode 100644
index 000000000..82fbd1bc9
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.c
@@ -0,0 +1,703 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+UINT64 mBelow4GMemoryLimit;=0D
+UINT64 mAbove4GMemoryLimit;=0D
+=0D
+EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+VTD_ACCESS_REQUEST *mAccessRequest =3D NULL;=0D
+UINTN mAccessRequestCount =3D 0;=0D
+UINTN mAccessRequestMaxCount =3D 0;=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_ACCESS_REQUEST *NewAccessRequest;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // Optimization for memory.=0D
+ //=0D
+ // If the last record is to IoMmuAccess=3D0,=0D
+ // Check previous records and remove the matched entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ if ((mAccessRequest[Index].Segment =3D=3D Segment) &&=0D
+ (mAccessRequest[Index].SourceId.Uint16 =3D=3D SourceId.Uint16) &=
&=0D
+ (mAccessRequest[Index].BaseAddress =3D=3D BaseAddress) &&=0D
+ (mAccessRequest[Index].Length =3D=3D Length) &&=0D
+ (mAccessRequest[Index].IoMmuAccess !=3D 0)) {=0D
+ //=0D
+ // Remove this record [Index].=0D
+ // No need to add the new record.=0D
+ //=0D
+ if (Index !=3D mAccessRequestCount - 1) {=0D
+ CopyMem (=0D
+ &mAccessRequest[Index],=0D
+ &mAccessRequest[Index + 1],=0D
+ sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index=
)=0D
+ );=0D
+ }=0D
+ ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCE=
SS_REQUEST));=0D
+ mAccessRequestCount--;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequestCount >=3D mAccessRequestMaxCount) {=0D
+ NewAccessRequest =3D AllocateZeroPool (sizeof(*NewAccessRequest) * (mA=
ccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));=0D
+ if (NewAccessRequest =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mAccessRequestMaxCount +=3D MAX_VTD_ACCESS_REQUEST;=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest)=
* mAccessRequestCount);=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NewAccessRequest;=0D
+ }=0D
+=0D
+ ASSERT (mAccessRequestCount < mAccessRequestMaxCount);=0D
+=0D
+ mAccessRequest[mAccessRequestCount].Segment =3D Segment;=0D
+ mAccessRequest[mAccessRequestCount].SourceId =3D SourceId;=0D
+ mAccessRequest[mAccessRequestCount].BaseAddress =3D BaseAddress;=0D
+ mAccessRequest[mAccessRequestCount].Length =3D Length;=0D
+ mAccessRequest[mAccessRequestCount].IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ mAccessRequestCount++;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process Access Requests from before DMAR table is installed.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessRequestedAccessAttribute (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));=0D
+=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "PCI(S%x.B%x.D%x.F%x) ",=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId.Bits.Bus,=0D
+ mAccessRequest[Index].SourceId.Bits.Device,=0D
+ mAccessRequest[Index].SourceId.Bits.Function=0D
+ ));=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "(0x%lx~0x%lx) - %lx\n",=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ ));=0D
+ Status =3D SetAccessAttribute (=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId,=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NULL;=0D
+ mAccessRequestCount =3D 0;=0D
+ mAccessRequestMaxCount =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));=0D
+}=0D
+=0D
+/**=0D
+ Return UEFI memory map information.=0D
+=0D
+ @param[out] Below4GMemoryLimit The below 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+ @param[out] Above4GMemoryLimit The above 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+=0D
+**/=0D
+VOID=0D
+ReturnUefiMemoryMap (=0D
+ OUT UINT64 *Below4GMemoryLimit,=0D
+ OUT UINT64 *Above4GMemoryLimit=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR *NextEfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR TempEfiEntry;=0D
+ UINTN EfiMemoryMapSize;=0D
+ UINTN EfiMapKey;=0D
+ UINTN EfiDescriptorSize;=0D
+ UINT32 EfiDescriptorVersion;=0D
+ UINT64 MemoryBlockLength;=0D
+=0D
+ *Below4GMemoryLimit =3D 0;=0D
+ *Above4GMemoryLimit =3D 0;=0D
+=0D
+ //=0D
+ // Get the EFI memory map.=0D
+ //=0D
+ EfiMemoryMapSize =3D 0;=0D
+ EfiMemoryMap =3D NULL;=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+=0D
+ do {=0D
+ //=0D
+ // Use size returned back plus 1 descriptor for the AllocatePool.=0D
+ // We don't just multiply by 2 since the "for" loop below terminates o=
n=0D
+ // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize=
=0D
+ // we process bogus entries and create bogus E820 entries.=0D
+ //=0D
+ EfiMemoryMap =3D (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapS=
ize);=0D
+ if (EfiMemoryMap =3D=3D NULL) {=0D
+ ASSERT (EfiMemoryMap !=3D NULL);=0D
+ return;=0D
+ }=0D
+=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (EfiMemoryMap);=0D
+ }=0D
+ } while (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Sort memory map from low to high=0D
+ //=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ while (NextEfiEntry < EfiMemoryMapEnd) {=0D
+ if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {=0D
+ CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTO=
R));=0D
+ }=0D
+=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptor=
Size);=0D
+ }=0D
+=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "MemoryMap:\n"));=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ MemoryBlockLength =3D (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12=
));=0D
+ DEBUG ((DEBUG_INFO, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry->T=
ype, EfiEntry->PhysicalStart, EfiEntry->PhysicalStart + MemoryBlockLength))=
;=0D
+ switch (EfiEntry->Type) {=0D
+ case EfiLoaderCode:=0D
+ case EfiLoaderData:=0D
+ case EfiBootServicesCode:=0D
+ case EfiBootServicesData:=0D
+ case EfiConventionalMemory:=0D
+ case EfiRuntimeServicesCode:=0D
+ case EfiRuntimeServicesData:=0D
+ case EfiACPIReclaimMemory:=0D
+ case EfiACPIMemoryNVS:=0D
+ case EfiReservedMemoryType:=0D
+ if ((EfiEntry->PhysicalStart + MemoryBlockLength) <=3D BASE_1MB) {=0D
+ //=0D
+ // Skip the memory block is under 1MB=0D
+ //=0D
+ } else if (EfiEntry->PhysicalStart >=3D BASE_4GB) {=0D
+ if (*Above4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Above4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ } else {=0D
+ if (*Below4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Below4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ }=0D
+ break;=0D
+ }=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);=0D
+ }=0D
+=0D
+ FreePool (EfiMemoryMap);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Result:\n"));=0D
+ DEBUG ((DEBUG_INFO, "Below4GMemoryLimit: 0x%016lx\n", *Below4GMemoryLim=
it));=0D
+ DEBUG ((DEBUG_INFO, "Above4GMemoryLimit: 0x%016lx\n", *Above4GMemoryLim=
it));=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackAlwaysEnablePageAttribute (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ EFI_STATUS Status;=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (Segment, SourceId);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device in the DeviceScope.=
=0D
+=0D
+ @param[in] DeviceScope the input device scope data structure=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device scope.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeDeviceScope (=0D
+ IN EDKII_PLATFORM_VTD_DEVICE_SCOPE *DeviceScope=0D
+ )=0D
+{=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceS=
cope->DeviceScope, &Bus, &Device, &Function);=0D
+=0D
+ if (DeviceScope->DeviceScope.Type =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYP=
E_PCI_BRIDGE) {=0D
+ //=0D
+ // Need scan the bridge and add all devices.=0D
+ //=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Device=
Scope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIS=
TER_OFFSET));=0D
+ Status =3D ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusN=
umber, ScanBusCallbackAlwaysEnablePageAttribute);=0D
+ return Status;=0D
+ } else {=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, Sour=
ceId);=0D
+ return Status;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device matching DeviceId.=0D
+=0D
+ @param[in] PciDeviceId the input PCI device ID=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device matching DeviceId.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributePciDeviceId (=0D
+ IN EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ UINTN PciIndex;=0D
+ PCI_DEVICE_DATA *PciDeviceData;=0D
+ EFI_STATUS Status;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ for (PciIndex =3D 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDevic=
eInfo->PciDeviceDataNumber; PciIndex++) {=0D
+ PciDeviceData =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciD=
eviceData[PciIndex];=0D
+=0D
+ if (((PciDeviceId->VendorId =3D=3D 0xFFFF) || (PciDeviceId->VendorId=
=3D=3D PciDeviceData->PciDeviceId.VendorId)) &&=0D
+ ((PciDeviceId->DeviceId =3D=3D 0xFFFF) || (PciDeviceId->DeviceId=
=3D=3D PciDeviceData->PciDeviceId.DeviceId)) &&=0D
+ ((PciDeviceId->RevisionId =3D=3D 0xFF) || (PciDeviceId->Revision=
Id =3D=3D PciDeviceData->PciDeviceId.RevisionId)) &&=0D
+ ((PciDeviceId->SubsystemVendorId =3D=3D 0xFFFF) || (PciDeviceId-=
SubsystemVendorId =3D=3D PciDeviceData->PciDeviceId.SubsystemVendorId)) &&==0D
+ ((PciDeviceId->SubsystemDeviceId =3D=3D 0xFFFF) || (PciDeviceId-=
SubsystemDeviceId =3D=3D PciDeviceData->PciDeviceId.SubsystemDeviceId)) ) ={=0D
+ Status =3D AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex=
].Segment, PciDeviceData->PciSourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ continue;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] DeviceInfo the exception device information=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device info.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeExceptionDeviceInfo (=0D
+ IN EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *DeviceInfo=0D
+ )=0D
+{=0D
+ switch (DeviceInfo->Type) {=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:=0D
+ return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1))=
;=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:=0D
+ return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1))=
;=0D
+ default:=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN DeviceInfoCount;=0D
+ VOID *DeviceInfo;=0D
+ EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // It is optional.=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEdkiiPlatformVTdPolicyProtocolGuid,=0D
+ NULL,=0D
+ (VOID **)&mPlatformVTdPolicy=0D
+ );=0D
+ if (!EFI_ERROR(Status)) {=0D
+ DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));=0D
+ Status =3D mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPol=
icy, &DeviceInfoCount, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ ThisDeviceInfo =3D DeviceInfo;=0D
+ for (Index =3D 0; Index < DeviceInfoCount; Index++) {=0D
+ if (ThisDeviceInfo->Type =3D=3D EDKII_PLATFORM_VTD_EXCEPTION_DEVIC=
E_INFO_TYPE_END) {=0D
+ break;=0D
+ }=0D
+ AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);=0D
+ ThisDeviceInfo =3D (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo=
->Length);=0D
+ }=0D
+ FreePool (DeviceInfo);=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd engine.=0D
+**/=0D
+VOID=0D
+SetupVtd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VOID *PciEnumerationComplete;=0D
+ UINTN Index;=0D
+ UINT64 Below4GMemoryLimit;=0D
+ UINT64 Above4GMemoryLimit;=0D
+ VTD_ROOT_TABLE_INFO RootTableInfo;=0D
+=0D
+ //=0D
+ // PCI Enumeration must be done=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEfiPciEnumerationCompleteProtocolGuid,=0D
+ NULL,=0D
+ &PciEnumerationComplete=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ ReturnUefiMemoryMap (&Below4GMemoryLimit, &Above4GMemoryLimit);=0D
+ Below4GMemoryLimit =3D ALIGN_VALUE_UP(Below4GMemoryLimit, SIZE_256MB);=0D
+ DEBUG ((DEBUG_INFO, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GM=
emoryLimit));=0D
+=0D
+ mBelow4GMemoryLimit =3D Below4GMemoryLimit;=0D
+ mAbove4GMemoryLimit =3D Above4GMemoryLimit;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_SETUP_VTD, Below4GMemoryLimit, Above4GMemoryL=
imit);=0D
+=0D
+ //=0D
+ // 1. setup=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "ParseDmarAcpiTable\n"));=0D
+ Status =3D ParseDmarAcpiTableDrhd ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));=0D
+ PrepareVtdConfig ();=0D
+=0D
+ //=0D
+ // 2. initialization=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));=0D
+ Status =3D SetupTranslationTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ InitializePlatformVTdPolicy ();=0D
+=0D
+ ParseDmarAcpiTableRmrr ();=0D
+=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) =3D=3D 0) {=0D
+ //=0D
+ // Support IOMMU access attribute request recording before DMAR table =
is installed.=0D
+ // Here is to process the requests.=0D
+ //=0D
+ ProcessRequestedAccessAttribute ();=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInf=
ormation[Index].Segment));=0D
+=0D
+ if (mVtdUnitInformation[Index].ExtRootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
Index].ExtRootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 1, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[Index].RootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Ind=
ex].RootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 0, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // 3. enable=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar\n"));=0D
+ Status =3D EnableDmar ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "DumpVtdRegs\n"));=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Notification function of ACPI Table change.=0D
+=0D
+ This is a notification function registered on ACPI Table change event.=0D
+=0D
+ @param Event Event whose notification function is being invoked.=
=0D
+ @param Context Pointer to the notification function's context.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+AcpiNotificationFunc (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetDmarAcpiTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ if (Status =3D=3D EFI_ALREADY_STARTED) {=0D
+ gBS->CloseEvent (Event);=0D
+ }=0D
+ return;=0D
+ }=0D
+ SetupVtd ();=0D
+ gBS->CloseEvent (Event);=0D
+}=0D
+=0D
+/**=0D
+ Exit boot service callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnExitBootServices (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnExitBootServices\n"));=0D
+=0D
+ DumpVtdRegsAll ();=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidate all\n"));=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss);=0D
+=0D
+ InvalidateContextCache (VtdIndex);=0D
+=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) {=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Legacy boot callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnLegacyBoot (=0D
+ EFI_EVENT Event,=0D
+ VOID *Context=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnLegacyBoot\n"));=0D
+ DumpVtdRegsAll ();=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_EVENT ExitBootServicesEvent;=0D
+ EFI_EVENT LegacyBootEvent;=0D
+ EFI_EVENT EventAcpi10;=0D
+ EFI_EVENT EventAcpi20;=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi10TableGuid,=0D
+ &EventAcpi10=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi20TableGuid,=0D
+ &EventAcpi20=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Signal the events initially for the case=0D
+ // that DMAR table has been installed.=0D
+ //=0D
+ gBS->SignalEvent (EventAcpi20);=0D
+ gBS->SignalEvent (EventAcpi10);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ TPL_CALLBACK,=0D
+ OnExitBootServices,=0D
+ NULL,=0D
+ &gEfiEventExitBootServicesGuid,=0D
+ &ExitBootServicesEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D EfiCreateEventLegacyBootEx (=0D
+ TPL_CALLBACK,=0D
+ OnLegacyBoot,=0D
+ NULL,=0D
+ &LegacyBootEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ return ;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.h
new file mode 100644
index 000000000..5cd59d18e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.h
@@ -0,0 +1,658 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef _DMAR_PROTECTION_H_=0D
+#define _DMAR_PROTECTION_H_=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiDxe.h>=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/PciSegmentLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/UefiLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/PerformanceLib.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/ReportStatusCodeLib.h>=0D
+#include <Library/HobLib.h>=0D
+=0D
+#include <Guid/EventGroup.h>=0D
+#include <Guid/Acpi.h>=0D
+=0D
+#include <Protocol/VtdLog.h>=0D
+#include <Protocol/DxeSmmReadyToLock.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+#include <Protocol/PciIo.h>=0D
+#include <Protocol/PciEnumerationComplete.h>=0D
+#include <Protocol/PlatformVtdPolicy.h>=0D
+#include <Protocol/IoMmu.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+=0D
+#include <IndustryStandard/Pci.h>=0D
+#include <IndustryStandard/DmaRemappingReportingTable.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (=
~((Alignment) - 1)))=0D
+#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))=
=0D
+=0D
+#define VTD_TPL_LEVEL TPL_NOTIFY=0D
+=0D
+//=0D
+// Use 256-bit descriptor=0D
+// Queue size is 128.=0D
+//=0D
+#define VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH 1=0D
+#define VTD_INVALIDATION_QUEUE_SIZE 0=0D
+=0D
+//=0D
+// This is the initial max PCI DATA number.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_PCI_DATA_NUMBER 0x100=0D
+=0D
+typedef struct {=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Segment;=0D
+ VTD_VER_REG VerReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_ROOT_ENTRY *RootEntryTable;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntryTable;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *FixedSecondLevelPagingEntry;=0D
+ BOOLEAN HasDirtyContext;=0D
+ BOOLEAN HasDirtyPages;=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ BOOLEAN Is5LevelPaging;=0D
+ UINT8 EnableQueuedInvalidation;=0D
+ VOID *QiDescBuffer;=0D
+ UINTN QiDescBufferSize;=0D
+} VTD_UNIT_INFORMATION;=0D
+=0D
+//=0D
+// This is the initial max ACCESS request.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_ACCESS_REQUEST 0x100=0D
+=0D
+typedef struct {=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 Length;=0D
+ UINT64 IoMmuAccess;=0D
+} VTD_ACCESS_REQUEST;=0D
+=0D
+=0D
+/**=0D
+ The scan bus callback function.=0D
+=0D
+ It is called in PCI bus scan for each PCI device under the bus.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The specific PCI device is processed in th=
e callback.=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *SCAN_BUS_FUNC_CALLBACK_FUNC) (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+extern EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;=0D
+=0D
+extern UINTN mVtdUnitNumber;=0D
+extern VTD_UNIT_INFORMATION *mVtdUnitInformation;=0D
+=0D
+extern UINT64 mBelow4GMemoryLimit;=0D
+extern UINT64 mAbove4GMemoryLimit;=0D
+=0D
+extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegs (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers for all VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegsAll (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd extended capability registers.=0D
+=0D
+ @param[in] ECapReg The extended capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdECapRegs (=0D
+ IN VTD_ECAP_REG *ECapReg=0D
+ );=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ );=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ );=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR RMRR table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR RMRR table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ );=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ );=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ );=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ );=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dmar=
AcpiTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
rAcpiTable.c
new file mode 100644
index 000000000..21f559983
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmarAcpiTab=
le.c
@@ -0,0 +1,398 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#pragma pack(1)=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT32 Entry;=0D
+} RSDT_TABLE;=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT64 Entry;=0D
+} XSDT_TABLE;=0D
+=0D
+#pragma pack()=0D
+=0D
+EFI_ACPI_DMAR_HEADER *mAcpiDmarTable =3D NULL;=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+**/=0D
+VOID=0D
+VtdDumpDmarTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VtdLibDumpAcpiDmar (NULL, NULL, (EFI_ACPI_DMAR_HEADER *) (UINTN) mAcpiDm=
arTable);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_DMAR_TABLE, mAcpiDmarTable->Header.Length=
, (VOID *)mAcpiDmarTable, mAcpiDmarTable->Header.Length); =0D
+}=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;=0D
+ UINT8 MyBus;=0D
+ UINT8 MyDevice;=0D
+ UINT8 MyFunction;=0D
+=0D
+ DmarPciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)((UINTN)(DmarDevScopeEntry + 1=
));=0D
+ MyBus =3D DmarDevScopeEntry->StartBusNumber;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ while ((UINTN)DmarPciPath + sizeof(EFI_ACPI_DMAR_PCI_PATH) < (UINTN)Dm=
arDevScopeEntry + DmarDevScopeEntry->Length) {=0D
+ MyBus =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, MyBus, M=
yDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=0D
+ DmarPciPath ++;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+ }=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ break;=0D
+ }=0D
+=0D
+ *Bus =3D MyBus;=0D
+ *Device =3D MyDevice;=0D
+ *Function =3D MyFunction;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR DRHD table.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] DmarDrhd The DRHD table.=0D
+=0D
+ @retval EFI_SUCCESS The DRHD table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessDrhd (=0D
+ IN UINTN VtdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D AllocateZeroPool (sizeof=
(PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVICE_DATA) * MAX_VTD_PCI_DATA_NUM=
BER);=0D
+ if (mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D=3D NULL) {=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Segment =3D DmarDrhd->SegmentNu=
mber;=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress =3D (UINTN)DmarDrhd->Re=
gisterBaseAddress;=0D
+ DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, Dma=
rDrhd->RegisterBaseAddress));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->Segment =3D =
DmarDrhd->SegmentNumber;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataMaxNumber =3D =
MAX_VTD_PCI_DATA_NUMBER;=0D
+=0D
+ if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) !=3D 0)=
{=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D TRUE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n"));=0D
+=0D
+ Status =3D ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Sc=
anBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ } else {=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D FALSE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n"));=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarDrhd + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Len=
gth) {=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: "));=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ DEBUG ((DEBUG_INFO,"PCI Endpoint"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ DEBUG ((DEBUG_INFO,"IOAPIC"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ DEBUG ((DEBUG_INFO,"MSI Capable HPET"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));=0D
+ break;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumb=
er, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, DmarDrhd->SegmentNumber, Sourc=
eId, DmarDevScopeEntry->Type, TRUE);=0D
+ if (EFI_ERROR (Status)) {=0D
+ //=0D
+ // There might be duplication for special device other than standard=
PCI device.=0D
+ //=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Dmar=
Drhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIST=
ER_OFFSET));=0D
+ Status =3D ScanPciBus ((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Se=
condaryBusNumber, ScanBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR RMRR table.=0D
+=0D
+ @param[in] DmarRmrr The RMRR table.=0D
+=0D
+ @retval EFI_SUCCESS The RMRR table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessRmrr (=0D
+ IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr-=
ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddres=s));=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarRmrr + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Len=
gth) {=0D
+ if (DmarDevScopeEntry->Type !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_=
ENDPOINT) {=0D
+ DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%=
x] \n", DmarDevScopeEntry->Type));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->Segment=
Number, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D SetAccessAttribute (=0D
+ DmarRmrr->SegmentNumber,=0D
+ SourceId,=0D
+ DmarRmrr->ReservedMemoryRegionBaseAddress,=0D
+ DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->=
ReservedMemoryRegionBaseAddress,=0D
+ EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Get VTd engine number.=0D
+**/=0D
+UINTN=0D
+GetVtdEngineNumber (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ UINTN VtdIndex;=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdIndex++;=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return VtdIndex ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+ UINTN VtdIndex;=0D
+=0D
+ mVtdUnitNumber =3D GetVtdEngineNumber ();=0D
+ DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));=0D
+ ASSERT (mVtdUnitNumber > 0);=0D
+ if (mVtdUnitNumber =3D=3D 0) {=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ mVtdUnitInformation =3D AllocateZeroPool (sizeof(*mVtdUnitInformation) *=
mVtdUnitNumber);=0D
+ ASSERT (mVtdUnitInformation !=3D NULL);=0D
+ if (mVtdUnitInformation =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ ASSERT (VtdIndex < mVtdUnitNumber);=0D
+ Status =3D ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarH=
eader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ VtdIndex++;=0D
+=0D
+ break;=0D
+=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ ASSERT (VtdIndex =3D=3D mVtdUnitNumber);=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibDumpPciDeviceInfo (NULL, NULL, mVtdUnitInformation[VtdIndex].Pci=
DeviceInfo);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_PCI_DEVICE,=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress,=
=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo,=0D
+ sizeof (PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVI=
CE_DATA) * mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataNumber=
);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_RMRR:=0D
+ Status =3D ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (mAcpiDmarTable !=3D NULL) {=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+=0D
+ mAcpiDmarTable =3D (EFI_ACPI_DMAR_HEADER *) EfiLocateFirstAcpiTable (=0D
+ EFI_ACPI_4_0_DMA_REMAPPING_T=
ABLE_SIGNATURE=0D
+ );=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ return EFI_NOT_FOUND;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));=0D
+ VtdDumpDmarTable();=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/I=
ntelVTdCoreDxe.c
new file mode 100644
index 000000000..6e8c87e1f
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.c
@@ -0,0 +1,787 @@
+/** @file=0D
+ Intel VTd driver.=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ );=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ );=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ )=0D
+{=0D
+ EFI_PCI_IO_PROTOCOL *PciIo;=0D
+ UINTN Seg;=0D
+ UINTN Bus;=0D
+ UINTN Dev;=0D
+ UINTN Func;=0D
+ EFI_STATUS Status;=0D
+ EDKII_PLATFORM_VTD_DEVICE_INFO DeviceInfo;=0D
+=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (mPlatformVTdPolicy !=3D NULL) {=0D
+ Status =3D mPlatformVTdPolicy->GetDeviceId (mPlatformVTdPolicy, Device=
Handle, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ *Segment =3D DeviceInfo.Segment;=0D
+ *SourceId =3D DeviceInfo.SourceId;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D gBS->HandleProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (V=
OID **)&PciIo);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ Status =3D PciIo->GetLocation (PciIo, &Seg, &Bus, &Dev, &Func);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ *Segment =3D (UINT16)Seg;=0D
+ SourceId->Bits.Bus =3D (UINT8)Bus;=0D
+ SourceId->Bits.Device =3D (UINT8)Dev;=0D
+ SourceId->Bits.Function =3D (UINT8)Func;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER DeviceAddress is not IoMmu Page size alig=
ned.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VTdSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ CHAR8 PerfToken[sizeof("VTD(S0000.B00.D00.F00)")];=
=0D
+ UINT32 Identifier;=0D
+ VTD_PROTOCOL_SET_ATTRIBUTE LogSetAttribute;=0D
+=0D
+ DumpVtdIfError ();=0D
+=0D
+ Status =3D DeviceHandleToSourceId (DeviceHandle, &Segment, &SourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuSetAttribute: "));=0D
+ DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment, SourceId.Bits.B=
us, SourceId.Bits.Device, SourceId.Bits.Function));=0D
+ DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length, I=
oMmuAccess));=0D
+=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ //=0D
+ // Record the entry to driver global variable.=0D
+ // As such once VTd is activated, the setting can be adopted.=0D
+ //=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) !=3D 0) {=0D
+ //=0D
+ // Force no IOMMU access attribute request recording before DMAR tab=
le is installed.=0D
+ //=0D
+ ASSERT_EFI_ERROR (EFI_NOT_READY);=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ Status =3D RequestAccessAttribute (Segment, SourceId, DeviceAddress, L=
ength, IoMmuAccess);=0D
+ } else {=0D
+ PERF_CODE (=0D
+ AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", S=
egment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_START_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=
=0D
+ );=0D
+=0D
+ Status =3D SetAccessAttribute (Segment, SourceId, DeviceAddress, Lengt=
h, IoMmuAccess);=0D
+=0D
+ PERF_CODE (=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_END_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=0D
+ );=0D
+ }=0D
+=0D
+ if (!EFI_ERROR(Status)) {=0D
+ SyncDeviceHandleToMapInfo (=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ LogSetAttribute.SourceId.Uint16 =3D SourceId.Uint16;=0D
+ LogSetAttribute.DeviceAddress =3D DeviceAddress;=0D
+ LogSetAttribute.Length =3D Length;=0D
+ LogSetAttribute.IoMmuAccess =3D IoMmuAccess;=0D
+ LogSetAttribute.Status =3D Status;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_IOMMU_SET_ATTRIBUTE, 0, &LogSetAttribute,=
sizeof (VTD_PROTOCOL_SET_ATTRIBUTE));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] Mapping The mapping value returned from Map().=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned =
by Map().=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by Mapping.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN VOID *Mapping,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ UINTN NumberOfPages;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+=0D
+ Status =3D GetDeviceInfoFromMapping (Mapping, &DeviceAddress, &NumberOfP=
ages);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ Status =3D VTdSetAttribute (=0D
+ This,=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ EFI_PAGES_TO_SIZE(NumberOfPages),=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+EDKII_IOMMU_PROTOCOL mIntelVTd =3D {=0D
+ EDKII_IOMMU_PROTOCOL_REVISION,=0D
+ IoMmuSetAttribute,=0D
+ IoMmuMap,=0D
+ IoMmuUnmap,=0D
+ IoMmuAllocateBuffer,=0D
+ IoMmuFreeBuffer,=0D
+};=0D
+=0D
+UINT8 *mVtdLogBuffer =3D NULL;=0D
+=0D
+UINT8 *mVtdLogDxeFreeBuffer =3D NULL;=0D
+UINT32 mVtdLogDxeBufferUsed =3D 0;=0D
+=0D
+UINT32 mVtdLogPeiPostMemBufferUsed =3D 0;=0D
+=0D
+UINT8 mVtdLogPeiError =3D 0;=0D
+UINT16 mVtdLogDxeError =3D 0;=0D
+=0D
+/**=0D
+ Allocate memory buffer for VTd log items.=0D
+=0D
+ @param[in] MemorySize Required memory buffer size.=0D
+=0D
+ @retval Buffer address=0D
+=0D
+**/=0D
+UINT8 *=0D
+EFIAPI=0D
+VTdLogAllocMemory (=0D
+ IN CONST UINT32 MemorySize=0D
+ )=0D
+{=0D
+ UINT8 *Buffer;=0D
+=0D
+ Buffer =3D NULL;=0D
+ if (mVtdLogDxeFreeBuffer !=3D NULL) {=0D
+ if ((mVtdLogDxeBufferUsed + MemorySize) <=3D PcdGet32 (PcdVTdDxeLogBuf=
ferSize)) {=0D
+ Buffer =3D mVtdLogDxeFreeBuffer;=0D
+=0D
+ mVtdLogDxeFreeBuffer +=3D MemorySize;=0D
+ mVtdLogDxeBufferUsed +=3D MemorySize;=0D
+ } else {=0D
+ mVtdLogDxeError |=3D VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ }=0D
+ return Buffer;=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM *Item;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ Item =3D (VTDLOG_EVENT_2PARAM *) VTdLogAllocMemory (sizeof (VTDLOG_EVENT=
_2PARAM));=0D
+ if (Item !=3D NULL) {=0D
+ Item->Data1 =3D Data1;=0D
+ Item->Data2 =3D Data2;=0D
+=0D
+ Item->Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_CONTEXT *Item;=0D
+ UINT32 EventSize;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ EventSize =3D sizeof (VTDLOG_EVENT_CONTEXT) + DataSize - 1;=0D
+=0D
+ Item =3D (VTDLOG_EVENT_CONTEXT *) VTdLogAllocMemory (EventSize);=0D
+ if (Item !=3D NULL) {=0D
+ Item->Param =3D Param;=0D
+ CopyMem (Item->Data, Data, DataSize);=0D
+=0D
+ Item->Header.DataSize =3D EventSize;=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+ =0D
+/**=0D
+ Get Event Items From Pei Pre-Mem Buffer=0D
+=0D
+ @param[in] Buffer Pre-Memory data buffer.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log event=
=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromPeiPreMemBuffer (=0D
+ IN VTDLOG_PEI_PRE_MEM_INFO *InfoBuffer,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINT64 EventCount;=0D
+ VTDLOG_EVENT_2PARAM Event;=0D
+=0D
+ if (InfoBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ EventCount =3D 0;=0D
+ for (Index =3D 0; Index < VTD_LOG_PEI_PRE_MEM_BAR_MAX; Index++) {=0D
+ if (InfoBuffer[Index].Mode =3D=3D VTD_LOG_PEI_PRE_MEM_NOT_USED) {=0D
+ continue;=0D
+ }=0D
+ if (CallbackHandle) {=0D
+ Event.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Event.Header.Timestamp =3D 0;=0D
+=0D
+ Event.Header.LogType =3D ((UINT64) 1) << VTDLOG_PEI_PRE_MEM_DMA_PROT=
ECT;=0D
+ Event.Data1 =3D InfoBuffer[Index].BarAddress;=0D
+ Event.Data2 =3D InfoBuffer[Index].Mode;=0D
+ Event.Data2 |=3D InfoBuffer[Index].Status<<8;=0D
+ CallbackHandle (Context, &Event.Header);=0D
+ }=0D
+ EventCount++;=0D
+ }=0D
+=0D
+ return EventCount;=0D
+}=0D
+=0D
+/**=0D
+ Get Event Items From Pei Post-Mem/Dxe Buffer=0D
+=0D
+ @param[in] Buffer Data buffer.=0D
+ @param[in] BufferUsed Data buffer used.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromBuffer (=0D
+ IN UINT8 *Buffer,=0D
+ IN UINT32 BufferUsed,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 Count;=0D
+ VTDLOG_EVENT_HEADER *Header;=0D
+=0D
+ Count =3D 0;=0D
+ if (Buffer !=3D NULL) {=0D
+ while (BufferUsed > 0) {=0D
+ Header =3D (VTDLOG_EVENT_HEADER *) Buffer;=0D
+ if (BufferUsed >=3D Header->DataSize) {=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, Header);=0D
+ }=0D
+ Buffer +=3D Header->DataSize;=0D
+ BufferUsed -=3D Header->DataSize;=0D
+ Count++;=0D
+ } else {=0D
+ BufferUsed =3D 0;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return Count;=0D
+}=0D
+=0D
+/**=0D
+ Generate the VTd log state.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdGenerateStateEvent (=0D
+ IN VTDLOG_EVENT_TYPE EventType,=0D
+ IN UINT64 Data1,=0D
+ IN UINT64 Data2,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM Item;=0D
+=0D
+ Item.Data1 =3D Data1;=0D
+ Item.Data2 =3D Data2;=0D
+=0D
+ Item.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item.Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item.Header.Timestamp =3D 0;=0D
+=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, &Item.Header);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Get the VTd log events.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdLogGetEvents (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 CountPeiPreMem;=0D
+ UINT64 CountPeiPostMem;=0D
+ UINT64 CountDxe;=0D
+ UINT8 *Buffer;=0D
+=0D
+ if (mVtdLogBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ //=0D
+ // PEI pre-memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (=
PcdVTdPeiPostMemLogBufferSize)];=0D
+ CountPeiPreMem =3D VTdGetEventItemsFromPeiPreMemBuffer ((VTDLOG_PEI_PRE_=
MEM_INFO *) Buffer, Context, CallbackHandle);=0D
+ DEBUG ((DEBUG_INFO, "Find %d in PEI pre mem phase\n", CountPeiPreMem));=
=0D
+=0D
+ //=0D
+ // PEI post memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize)];=0D
+ CountPeiPostMem =3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogPeiPostMe=
mBufferUsed, Context, CallbackHandle);=0D
+ if (mVtdLogPeiError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_PEI_BASIC, mVtdLogPeiError, 0, Context, =
CallbackHandle);=0D
+ CountPeiPostMem++;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "Find %d in PEI post mem phase\n", CountPeiPostMem))=
;=0D
+=0D
+ //=0D
+ // DXE phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[0];=0D
+ CountDxe =3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogDxeBufferUsed, C=
ontext, CallbackHandle);=0D
+ if (mVtdLogDxeError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_DXE_BASIC, mVtdLogDxeError, 0, Context, =
CallbackHandle);=0D
+ CountDxe++;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "Find %d in DXE phase\n", CountDxe));=0D
+=0D
+ return CountPeiPreMem + CountPeiPostMem + CountDxe;=0D
+}=0D
+=0D
+EDKII_VTD_LOG_PROTOCOL mIntelVTdLog =3D {=0D
+ EDKII_VTD_LOG_PROTOCOL_REVISION,=0D
+ VTdLogGetEvents=0D
+};=0D
+=0D
+/**=0D
+ Initializes the VTd Log.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogInitialize(=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINT32 TotalBufferSize;=0D
+ EFI_STATUS Status;=0D
+ VOID *HobPtr;=0D
+ VTDLOG_PEI_BUFFER_HOB *HobPeiBuffer;=0D
+ EFI_HANDLE Handle;=0D
+ UINT32 BufferOffset;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ }=0D
+=0D
+ if (mVtdLogBuffer !=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ TotalBufferSize =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTd=
PeiPostMemLogBufferSize) + sizeof (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_P=
RE_MEM_BAR_MAX;=0D
+=0D
+ Status =3D gBS->AllocatePool (EfiBootServicesData, TotalBufferSize, &mVt=
dLogBuffer);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // DXE Buffer=0D
+ //=0D
+ if (PcdGet32 (PcdVTdDxeLogBufferSize) > 0) {=0D
+ mVtdLogDxeFreeBuffer =3D mVtdLogBuffer;=0D
+ mVtdLogDxeBufferUsed =3D 0;=0D
+ }=0D
+=0D
+ //=0D
+ // Get PEI pre-memory buffer offset=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTdPei=
PostMemLogBufferSize);=0D
+=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ HobPeiBuffer =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ //=0D
+ // Copy PEI pre-memory phase VTd log.=0D
+ //=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], &HobPeiBuffer->PreMemInfo, size=
of (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+=0D
+ //=0D
+ // Copy PEI post-memory pase VTd log.=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize);=0D
+ if (PcdGet32 (PcdVTdPeiPostMemLogBufferSize) > 0) {=0D
+ if (HobPeiBuffer->PostMemBufferUsed > 0) {=0D
+ mVtdLogPeiPostMemBufferUsed =3D HobPeiBuffer->PostMemBufferUsed;=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], (UINT8 *) (UINTN) HobPeiBuf=
fer->PostMemBuffer, mVtdLogPeiPostMemBufferUsed);=0D
+ }=0D
+ }=0D
+=0D
+ mVtdLogPeiError =3D HobPeiBuffer->VtdLogPeiError;=0D
+ } else {=0D
+ //=0D
+ // Do not find PEI Vtd log, clear PEI pre-memory phase buffer.=0D
+ //=0D
+ ZeroMem (&mVtdLogBuffer[BufferOffset], sizeof (VTDLOG_PEI_PRE_MEM_INFO=
) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+ }=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiVTdLogProtocolGuid,=0D
+ &mIntelVTdLog,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+}=0D
+=0D
+/**=0D
+ Initialize the VTd driver.=0D
+=0D
+ @param[in] ImageHandle ImageHandle of the loaded driver=0D
+ @param[in] SystemTable Pointer to the System Table=0D
+=0D
+ @retval EFI_SUCCESS The Protocol is installed.=0D
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial=
ize driver.=0D
+ @retval EFI_DEVICE_ERROR A device error occurred attempting to ini=
tialize the driver.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IntelVTdInitialize (=0D
+ IN EFI_HANDLE ImageHandle,=0D
+ IN EFI_SYSTEM_TABLE *SystemTable=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_HANDLE Handle;=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VTdLogInitialize ();=0D
+=0D
+ InitializeDmaProtection ();=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiIoMmuProtocolGuid, &mIntelVTd,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL, Status, 0);=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.inf
new file mode 100644
index 000000000..6f3c9e7df
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.inf
@@ -0,0 +1,92 @@
+## @file=0D
+# Intel VTd DXE Driver.=0D
+#=0D
+# This driver initializes VTd engine based upon DMAR ACPI tables=0D
+# and provide DMA protection to PCI or ACPI device.=0D
+#=0D
+# Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdCoreDxe=0D
+ MODULE_UNI_FILE =3D IntelVTdCoreDxe.uni=0D
+ FILE_GUID =3D 5c83381f-34d3-4672-b8f3-83c3d6f3b00e=
=0D
+ MODULE_TYPE =3D DXE_DRIVER=0D
+ VERSION_STRING =3D 1.0=0D
+ ENTRY_POINT =3D IntelVTdInitialize=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D IA32 X64 EBC=0D
+#=0D
+#=0D
+=0D
+[Sources]=0D
+ IntelVTdCoreDxe.c=0D
+ BmDma.c=0D
+ DmaProtection.c=0D
+ DmaProtection.h=0D
+ DmarAcpiTable.c=0D
+ PciInfo.c=0D
+ TranslationTable.c=0D
+ TranslationTableEx.c=0D
+ VtdReg.c=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ UefiDriverEntryPoint=0D
+ UefiBootServicesTableLib=0D
+ BaseLib=0D
+ IoLib=0D
+ HobLib=0D
+ PciSegmentLib=0D
+ BaseMemoryLib=0D
+ MemoryAllocationLib=0D
+ UefiLib=0D
+ CacheMaintenanceLib=0D
+ PerformanceLib=0D
+ PrintLib=0D
+ ReportStatusCodeLib=0D
+ IntelVTdPeiDxeLib=0D
+=0D
+[Guids]=0D
+ gVTdLogBufferHobGuid ## CONSUMES=0D
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi20TableGuid=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi10TableGuid=0D
+=0D
+[Protocols]=0D
+ gEdkiiIoMmuProtocolGuid ## PRODUCES=0D
+ gEfiPciIoProtocolGuid ## CONSUMES=0D
+ gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES=0D
+ gEdkiiPlatformVTdPolicyProtocolGuid ## SOMETIMES_CONSUMES=0D
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES=0D
+ gEdkiiVTdLogProtocolGuid ## PRODUCES=0D
+=0D
+[Pcd]=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdDxeLogBufferSize ## CONSUME=
S=0D
+=0D
+[Depex]=0D
+ gEfiPciRootBridgeIoProtocolGuid=0D
+=0D
+[UserExtensions.TianoCore."ExtraFiles"]=0D
+ IntelVTdCoreDxeExtra.uni=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.uni
new file mode 100644
index 000000000..73d2c83c4
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Module Localized Abstract and Description Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Intel VTd CORE DX=
E Driver."=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "This driver initi=
alizes VTd engine based upon DMAR ACPI tables and provide DMA protection to=
PCI or ACPI device."=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxeExtra.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCo=
reDxe/IntelVTdCoreDxeExtra.uni
new file mode 100644
index 000000000..7f1aec65e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxeExtra.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Localized Strings and Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+#string STR_PROPERTIES_MODULE_NAME=0D
+#language en-US=0D
+"Intel VTd CORE DXE Driver"=0D
+=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciI=
nfo.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
new file mode 100644
index 000000000..394ef734c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
@@ -0,0 +1,419 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ return (UINTN)-1;=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if ((PciSourceId->Bits.Bus =3D=3D SourceId.Bits.Bus) &&=0D
+ (PciSourceId->Bits.Device =3D=3D SourceId.Bits.Device) &&=0D
+ (PciSourceId->Bits.Function =3D=3D SourceId.Bits.Function) ) {=0D
+ return Index;=0D
+ }=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ )=0D
+{=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ UINTN PciDataIndex;=0D
+ UINTN Index;=0D
+ //PCI_DEVICE_DATA *NewPciDeviceData;=0D
+ PCI_DEVICE_INFORMATION *NewPciDeviceInfo;=0D
+ EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId;=0D
+=0D
+ PciDeviceInfo =3D mVtdUnitInformation[VtdIndex].PciDeviceInfo;=0D
+=0D
+ if (PciDeviceInfo->IncludeAllFlag) {=0D
+ //=0D
+ // Do not register device in other VTD Unit=0D
+ //=0D
+ for (Index =3D 0; Index < VtdIndex; Index++) {=0D
+ PciDataIndex =3D GetPciDataIndex (Index, Segment, SourceId);=0D
+ if (PciDataIndex !=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%=
02x already registered by Other Vtd(%d)\n", Segment, SourceId.Bits.Bus, Sou=
rceId.Bits.Device, SourceId.Bits.Function, Index));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ //=0D
+ // Register new=0D
+ //=0D
+=0D
+ if (PciDeviceInfo->PciDeviceDataNumber >=3D PciDeviceInfo->PciDeviceDa=
taMaxNumber) {=0D
+ //=0D
+ // Reallocate=0D
+ //=0D
+ NewPciDeviceInfo =3D AllocateZeroPool (sizeof (PCI_DEVICE_INFORMATIO=
N) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber + MA=
X_VTD_PCI_DATA_NUMBER));=0D
+ if (NewPciDeviceInfo =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ CopyMem (NewPciDeviceInfo, PciDeviceInfo, sizeof (PCI_DEVICE_INFORMA=
TION) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber +=
MAX_VTD_PCI_DATA_NUMBER));=0D
+ FreePool (PciDeviceInfo);=0D
+=0D
+ NewPciDeviceInfo->PciDeviceDataMaxNumber +=3D MAX_VTD_PCI_DATA_NUMBE=
R;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ }=0D
+=0D
+ ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceD=
ataMaxNumber);=0D
+=0D
+ PciSourceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciSourceId;=0D
+ PciSourceId->Bits.Bus =3D SourceId.Bits.Bus;=0D
+ PciSourceId->Bits.Device =3D SourceId.Bits.Device;=0D
+ PciSourceId->Bits.Function =3D SourceId.Bits.Function;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x"=
, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)=
);=0D
+=0D
+ PciDeviceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciDeviceId;=0D
+ if ((DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) =
||=0D
+ (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=
=0D
+ PciDeviceId->VendorId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->DeviceId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_DEVICE_ID_OFFSET));=0D
+ PciDeviceId->RevisionId =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS=
(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, =
PCI_REVISION_ID_OFFSET));=0D
+=0D
+ DEBUG ((DEBUG_INFO, " (%04x:%04x:%02x", PciDeviceId->VendorId, PciDe=
viceId->DeviceId, PciDeviceId->RevisionId));=0D
+=0D
+ if (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT)=
{=0D
+ PciDeviceId->SubsystemVendorId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->SubsystemDeviceId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_ID_OFFSET));=0D
+ DEBUG ((DEBUG_INFO, ":%04x:%04x", PciDeviceId->SubsystemVendorId, =
PciDeviceId->SubsystemDeviceId));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, ")"));=0D
+ }=0D
+=0D
+ PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDeviceDataNumber].Devic=
eType =3D DeviceType;=0D
+=0D
+ if ((DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) &&=
=0D
+ (DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=0D
+ DEBUG ((DEBUG_INFO, " (*)"));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "\n"));=0D
+=0D
+ PciDeviceInfo->PciDeviceDataNumber++;=0D
+ } else {=0D
+ if (CheckExist) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02=
x already registered\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, =
SourceId.Bits.Function));=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to register PCI device.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN VtdIndex;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT8 DeviceType;=0D
+ EFI_STATUS Status;=0D
+=0D
+ VtdIndex =3D (UINTN)Context;=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Dev=
ice, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, De=
vice, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, Segment, SourceId, DeviceType, F=
ALSE);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ UINT8 HeaderType;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT16 VendorID;=0D
+ UINT16 DeviceID;=0D
+ EFI_STATUS Status;=0D
+=0D
+ // Scan the PCI bus for devices=0D
+ for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) {=0D
+ for (Function =3D 0; Function <=3D PCI_MAX_FUNC; Function++) {=0D
+ VendorID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_VENDOR_ID_OFFSET));=0D
+ DeviceID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_DEVICE_ID_OFFSET));=0D
+ if (VendorID =3D=3D 0xFFFF && DeviceID =3D=3D 0xFFFF) {=0D
+ if (Function =3D=3D 0) {=0D
+ //=0D
+ // If function 0 is not implemented, do not scan other functions=
.=0D
+ //=0D
+ break;=0D
+ }=0D
+ continue;=0D
+ }=0D
+=0D
+ Status =3D Callback (Context, Segment, Bus, Device, Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus,=
Device, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(=
Segment, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=
=0D
+ DEBUG ((DEBUG_INFO," ScanPciBus: PCI bridge S%04x B%02x D%02x F=
%02x (SecondBus:%02x)\n", Segment, Bus, Device, Function, SecondaryBusNumbe=
r));=0D
+ if (SecondaryBusNumber !=3D 0) {=0D
+ Status =3D ScanPciBus (Context, Segment, SecondaryBusNumber, C=
allback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (Function =3D=3D 0) {=0D
+ HeaderType =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, B=
us, Device, 0, PCI_HEADER_TYPE_OFFSET));=0D
+ if ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) =3D=3D 0x00) {=0D
+ //=0D
+ // It is not a multi-function device, do not scan other function=
s.=0D
+ //=0D
+ break;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ UINTN HandleCount;=0D
+ EFI_HANDLE *HandleBuffer;=0D
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;=0D
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ScanAllPciBus ()\n"));=0D
+=0D
+ Status =3D gBS->LocateHandleBuffer (=0D
+ ByProtocol,=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ NULL,=0D
+ &HandleCount,=0D
+ &HandleBuffer=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Find %d root bridges\n", HandleCount));=0D
+=0D
+ for (Index =3D 0; Index < HandleCount; Index++) {=0D
+ Status =3D gBS->HandleProtocol (=0D
+ HandleBuffer[Index],=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ (VOID **) &PciRootBridgeIo=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) =
&Descriptors);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ while (Descriptors->Desc !=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ if (Descriptors->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_BUS) {=0D
+ break;=0D
+ }=0D
+ Descriptors++;=0D
+ }=0D
+=0D
+ if (Descriptors->Desc =3D=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ continue;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Scan root bridges : %d, Segment : %d, Bus : 0x%02X=
\n", Index, PciRootBridgeIo->SegmentNumber, Descriptors->AddrRangeMin));=0D
+ Status =3D ScanPciBus(Context, (UINT16) PciRootBridgeIo->SegmentNumber=
, (UINT8) Descriptors->AddrRangeMin, Callback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ FreePool(HandleBuffer);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ThisContextEntry;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ThisExtContextEntry;=0D
+ UINTN PciDataIndex;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ continue;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ continue;=0D
+ }=0D
+=0D
+// DEBUG ((DEBUG_INFO,"FindVtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n=
", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bit=
s.Function));=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D 0) {=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[So=
urceId.Index.RootIndex];=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_=
ADDRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.L=
owerContextTablePointerHi) ;=0D
+ ThisExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.Contex=
tIndex];=0D
+ if (ThisExtContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D ThisExtContextEntry;=0D
+ *ContextEntry =3D NULL;=0D
+ } else {=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId=
.Index.RootIndex];=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS=
(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointer=
Hi) ;=0D
+ ThisContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex=
];=0D
+ if (ThisContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D NULL;=0D
+ *ContextEntry =3D ThisContextEntry;=0D
+ }=0D
+=0D
+ return VtdIndex;=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/=
TranslationTable.c
new file mode 100644
index 000000000..37ca6e405
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
Table.c
@@ -0,0 +1,1112 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ )=0D
+{=0D
+ VOID *Addr;=0D
+=0D
+ Addr =3D AllocatePages (Pages);=0D
+ if (Addr =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ ZeroMem (Addr, EFI_PAGES_TO_SIZE(Pages));=0D
+ return Addr;=0D
+}=0D
+=0D
+/**=0D
+ Set second level paging entry attribute based upon IoMmuAccess.=0D
+=0D
+ @param[in] PtEntry The paging entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+**/=0D
+VOID=0D
+SetSecondLevelPagingEntryAttribute (=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PtEntry,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ PtEntry->Bits.Read =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_READ) !=3D 0)=
;=0D
+ PtEntry->Bits.Write =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_WRITE) !=3D 0=
);=0D
+}=0D
+=0D
+/**=0D
+ Create context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create context entry.=
=0D
+**/=0D
+EFI_STATUS=0D
+CreateContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTR=
Y_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CON=
TEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].RootEntryTable =3D (VTD_ROOT_ENTRY *)Buffe=
r;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId.I=
ndex.RootIndex];=0D
+ if (RootEntry->Bits.Present =3D=3D 0) {=0D
+ RootEntry->Bits.ContextTablePointerLo =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 12);=0D
+ RootEntry->Bits.ContextTablePointerHi =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 32);=0D
+ RootEntry->Bits.Present =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(R=
ootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi=
) ;=0D
+ ContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex];=0D
+ ContextEntry->Bits.TranslationType =3D 0;=0D
+ ContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n", mVtdUnitInform=
ation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.=
Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Roo=
tEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry table.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] MemoryBase The base of the memory.=0D
+ @param[in] MemoryLimit The limit of the memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntryTable (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 MemoryBase,=0D
+ IN UINT64 MemoryLimit,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Lvl5Start;=0D
+ UINTN Lvl5End;=0D
+ UINTN Lvl4PagesStart;=0D
+ UINTN Lvl4PagesEnd;=0D
+ UINTN Lvl4Start;=0D
+ UINTN Lvl4End;=0D
+ UINTN Lvl3Start;=0D
+ UINTN Lvl3End;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 EndAddress;=0D
+=0D
+ if (MemoryLimit =3D=3D 0) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ Lvl4PagesStart =3D 0;=0D
+ Lvl4PagesEnd =3D 0;=0D
+ Lvl4PtEntry =3D NULL;=0D
+ Lvl5PtEntry =3D NULL;=0D
+=0D
+ BaseAddress =3D ALIGN_VALUE_LOW(MemoryBase, SIZE_2MB);=0D
+ EndAddress =3D ALIGN_VALUE_UP(MemoryLimit, SIZE_2MB);=0D
+ DEBUG ((DEBUG_INFO,"CreateSecondLevelPagingEntryTable: BaseAddress - 0x%=
016lx, EndAddress - 0x%016lx\n", BaseAddress, EndAddress));=0D
+=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ SecondLevelPagingEntry =3D AllocateZeroPages (1);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry, EFI_PAG=
ES_TO_SIZE(1));=0D
+ }=0D
+=0D
+ //=0D
+ // If no access is needed, just create not present entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ return SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D RShiftU64 (EndAddress - 1, 48) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start, =
Lvl5End));=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+=0D
+ Lvl4PagesStart =3D (Lvl5Start<<9) | Lvl4Start;=0D
+ Lvl4PagesEnd =3D (Lvl5End<<9) | Lvl4End;=0D
+ DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", L=
vl4PagesStart, Lvl4PagesEnd));=0D
+=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ } else {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D Lvl5Start;=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, =
Lvl4End));=0D
+=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ }=0D
+=0D
+ for (Index5 =3D Lvl5Start; Index5 <=3D Lvl5End; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ Lvl5PtEntry[Index5].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index5));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl5PtEntry[Index5].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+ Lvl4Start =3D Lvl4PagesStart & 0x1FF;=0D
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {=0D
+ Lvl4End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;=0D
+ Lvl4PagesStart =3D (Index5+1)<<9;=0D
+ } else {=0D
+ Lvl4End =3D Lvl4PagesEnd & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\n=
", Index5, Lvl4Start, Lvl4End));=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D Lvl4Start; Index4 <=3D Lvl4End; Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ Lvl4PtEntry[Index4].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index4));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl3Start =3D RShiftU64 (BaseAddress, 30) & 0x1FF;=0D
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=3D EndAddres=
s) {=0D
+ Lvl3End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;=0D
+ } else {=0D
+ Lvl3End =3D RShiftU64 (EndAddress - 1, 30) & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n=
", Index4, Lvl3Start, Lvl3End));=0D
+=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D Lvl3Start; Index3 <=3D Lvl3End; Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ Lvl3PtEntry[Index3].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages =
(1);=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%=
x)!!!!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint6=
4, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_=
IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ Lvl2PtEntry[Index2].Uint64 =3D BaseAddress;=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuA=
ccess);=0D
+ Lvl2PtEntry[Index2].Bits.PageSize =3D 1;=0D
+ BaseAddress +=3D SIZE_2MB;=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UIN=
TN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN=
)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start], (UINTN)&=
Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex, =
SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess, Is5LevelPaging=
);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ if (mAbove4GMemoryLimit !=3D 0) {=0D
+ ASSERT (mAbove4GMemoryLimit > BASE_4GB);=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex=
, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess, Is5Le=
velPaging);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ }=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG((DEBUG_INFO, "CreateContextEntry - %d\n", Index));=0D
+=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.SMTS) {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));=0D
+ ASSERT(FALSE);=0D
+ Status =3D EFI_UNSUPPORTED;=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ } else {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ //=0D
+ // To compatible with pervious VTd engine=0D
+ // It was ECS(Extended Context Support) bit.=0D
+ //=0D
+ Status =3D CreateExtContextEntry (Index);=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ }=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR second level paging entry.=0D
+=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+DumpSecondLevelPagingEntry (=0D
+ IN VOID *SecondLevelPagingEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Index1;=0D
+ UINTN Lvl5IndexEnd;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl1PtEntry;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x, Is5LevelPagin=
g - %d\n", SecondLevelPagingEntry, Is5LevelPaging));=0D
+=0D
+ Lvl5IndexEnd =3D Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY) : 1;=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+=0D
+ for (Index5 =3D 0; Index5 < Lvl5IndexEnd; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n", Index=
5, Lvl5PtEntry[Index5].Uint64));=0D
+ }=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_EN=
TRY); Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index=
4, Lvl4PtEntry[Index4].Uint64));=0D
+ }=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_=
ENTRY); Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", In=
dex3, Lvl3PtEntry[Index3].Uint64));=0D
+ }=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ if (Lvl2PtEntry[Index2].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",=
Index2, Lvl2PtEntry[Index2].Uint64));=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Bits.PageSize =3D=3D 0) {=0D
+ Lvl1PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64=
BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.A=
ddressHi);=0D
+ for (Index1 =3D 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_P=
AGING_ENTRY); Index1++) {=0D
+ if (Lvl1PtEntry[Index1].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016=
lx\n", Index1, Lvl1PtEntry[Index1].Uint64));=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+}=0D
+=0D
+/**=0D
+ Invalid page entry.=0D
+=0D
+ @param VtdIndex The VTd engine index.=0D
+**/=0D
+VOID=0D
+InvalidatePageEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateVtdIOTLBGlobal (VtdIndex);=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D FALSE;=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D FALSE;=0D
+}=0D
+=0D
+#define VTD_PG_R BIT0=0D
+#define VTD_PG_W BIT1=0D
+#define VTD_PG_X BIT2=0D
+#define VTD_PG_EMT (BIT3 | BIT4 | BIT5)=0D
+#define VTD_PG_TM (BIT62)=0D
+=0D
+#define VTD_PG_PS BIT7=0D
+=0D
+#define PAGE_PROGATE_BITS (VTD_PG_TM | VTD_PG_EMT | VTD_PG_W | VT=
D_PG_R)=0D
+=0D
+#define PAGING_4K_MASK 0xFFF=0D
+#define PAGING_2M_MASK 0x1FFFFF=0D
+#define PAGING_1G_MASK 0x3FFFFFFF=0D
+=0D
+#define PAGING_VTD_INDEX_MASK 0x1FF=0D
+=0D
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull=0D
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull=0D
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull=0D
+=0D
+typedef enum {=0D
+ PageNone,=0D
+ Page4K,=0D
+ Page2M,=0D
+ Page1G,=0D
+} PAGE_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ PAGE_ATTRIBUTE Attribute;=0D
+ UINT64 Length;=0D
+ UINT64 AddressMask;=0D
+} PAGE_ATTRIBUTE_TABLE;=0D
+=0D
+PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D {=0D
+ {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},=0D
+ {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},=0D
+ {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},=0D
+};=0D
+=0D
+/**=0D
+ Return length according to page attributes.=0D
+=0D
+ @param[in] PageAttributes The page attribute of the page entry.=0D
+=0D
+ @return The length of page entry.=0D
+**/=0D
+UINTN=0D
+PageAttributeToLength (=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ for (Index =3D 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttrib=
uteTable[0]); Index++) {=0D
+ if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) {=0D
+ return (UINTN)mPageAttributeTable[Index].Length;=0D
+ }=0D
+ }=0D
+ return 0;=0D
+}=0D
+=0D
+/**=0D
+ Return page table entry to match the address.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd e=
ngine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in V=
Td table for the device.=0D
+ @param[in] Address The address to be checked.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+ @param[out] PageAttributes The page attribute of the page ent=
ry.=0D
+=0D
+ @return The page entry.=0D
+**/=0D
+VOID *=0D
+GetSecondLevelPageTableEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN PHYSICAL_ADDRESS Address,=0D
+ IN BOOLEAN Is5LevelPaging,=0D
+ OUT PAGE_ATTRIBUTE *PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index1;=0D
+ UINTN Index2;=0D
+ UINTN Index3;=0D
+ UINTN Index4;=0D
+ UINTN Index5;=0D
+ UINT64 *L1PageTable;=0D
+ UINT64 *L2PageTable;=0D
+ UINT64 *L3PageTable;=0D
+ UINT64 *L4PageTable;=0D
+ UINT64 *L5PageTable;=0D
+=0D
+ Index5 =3D ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;=0D
+ Index4 =3D ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;=0D
+ Index3 =3D ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;=0D
+ Index2 =3D ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;=0D
+ Index1 =3D ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ L5PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ L5PageTable[Index5] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\n=
", Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5], SIZE_4KB=
);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *=
)&L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5], sizeof(=
L5PageTable[Index5]));=0D
+ }=0D
+ L4PageTable =3D (UINT64 *)(UINTN)(L5PageTable[Index5] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ } else {=0D
+ L4PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ L4PageTable[Index4] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n",=
Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L4PageTable[Index4], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L4PageTable[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L4PageTable[Index4], sizeof(L4=
PageTable[Index4]));=0D
+ }=0D
+=0D
+ L3PageTable =3D (UINT64 *)(UINTN)(L4PageTable[Index4] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ L3PageTable[Index3] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!=
!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L3PageTable[Index3], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L3PageTable[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L3PageTable[Index3], sizeof(L3=
PageTable[Index3]));=0D
+ }=0D
+ if ((L3PageTable[Index3] & VTD_PG_PS) !=3D 0) {=0D
+ // 1G=0D
+ *PageAttribute =3D Page1G;=0D
+ return &L3PageTable[Index3];=0D
+ }=0D
+=0D
+ L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L2PageTable[Index2] =3D=3D 0) {=0D
+ L2PageTable[Index2] =3D Address & PAGING_2M_ADDRESS_MASK_64;=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L2PageTable[Index2], 0);=0D
+ L2PageTable[Index2] |=3D VTD_PG_PS;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L2PageTable[Index2], sizeof(L2=
PageTable[Index2]));=0D
+ }=0D
+ if ((L2PageTable[Index2] & VTD_PG_PS) !=3D 0) {=0D
+ // 2M=0D
+ *PageAttribute =3D Page2M;=0D
+ return &L2PageTable[Index2];=0D
+ }=0D
+=0D
+ // 4k=0D
+ L1PageTable =3D (UINT64 *)(UINTN)(L2PageTable[Index2] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if ((L1PageTable[Index1] =3D=3D 0) && (Address !=3D 0)) {=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ *PageAttribute =3D Page4K;=0D
+ return &L1PageTable[Index1];=0D
+}=0D
+=0D
+/**=0D
+ Modify memory attributes of page entry.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[out] IsModified TRUE means page table modified. FALSE mean=
s page table not modified.=0D
+**/=0D
+VOID=0D
+ConvertSecondLevelPageEntryAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN UINT64 IoMmuAccess,=0D
+ OUT BOOLEAN *IsModified=0D
+ )=0D
+{=0D
+ UINT64 CurrentPageEntry;=0D
+ UINT64 NewPageEntry;=0D
+=0D
+ CurrentPageEntry =3D PageEntry->Uint64;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry));=0D
+ NewPageEntry =3D PageEntry->Uint64;=0D
+ if (CurrentPageEntry !=3D NewPageEntry) {=0D
+ *IsModified =3D TRUE;=0D
+ DEBUG ((DEBUG_VERBOSE, "ConvertSecondLevelPageEntryAttribute 0x%lx", C=
urrentPageEntry));=0D
+ DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));=0D
+ } else {=0D
+ *IsModified =3D FALSE;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ This function returns if there is need to split page entry.=0D
+=0D
+ @param[in] BaseAddress The base address to be checked.=0D
+ @param[in] Length The length to be checked.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+=0D
+ @retval SplitAttributes on if there is need to split page entry.=0D
+**/=0D
+PAGE_ATTRIBUTE=0D
+NeedSplitPage (=0D
+ IN PHYSICAL_ADDRESS BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINT64 PageEntryLength;=0D
+=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+=0D
+ if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D Pag=
eEntryLength)) {=0D
+ return PageNone;=0D
+ }=0D
+=0D
+ if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) {=0D
+ return Page4K;=0D
+ }=0D
+=0D
+ return Page2M;=0D
+}=0D
+=0D
+/**=0D
+ This function splits one page entry to small page entries.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry to be splitted.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+ @param[in] SplitAttribute How to split the page entry.=0D
+=0D
+ @retval RETURN_SUCCESS The page entry is splitted.=0D
+ @retval RETURN_UNSUPPORTED The page entry does not support to be =
splitted.=0D
+ @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.=0D
+**/=0D
+RETURN_STATUS=0D
+SplitSecondLevelPage (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN PAGE_ATTRIBUTE PageAttribute,=0D
+ IN PAGE_ATTRIBUTE SplitAttribute=0D
+ )=0D
+{=0D
+ UINT64 BaseAddress;=0D
+ UINT64 *NewPageEntry;=0D
+ UINTN Index;=0D
+=0D
+ ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G);=0D
+=0D
+ if (PageAttribute =3D=3D Page2M) {=0D
+ //=0D
+ // Split 2M to 4K=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page4K);=0D
+ if (SplitAttribute =3D=3D Page4K) {=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_2M_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | (PageEn=
try->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else if (PageAttribute =3D=3D Page1G) {=0D
+ //=0D
+ // Split 1G to 2M=0D
+ // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K =
to get more compact page table.=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K);=
=0D
+ if ((SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K)) {=
=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_1G_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | VTD_PG_=
PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory on second level page entry=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetSecondLevelPagingAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry;=0D
+ PAGE_ATTRIBUTE PageAttribute;=0D
+ UINTN PageEntryLength;=0D
+ PAGE_ATTRIBUTE SplitAttribute;=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN IsEntryModified;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetSecondLevelPagingAttribute (%d) (0x%016lx - 0x=
%016lx : %x) \n", VtdIndex, BaseAddress, Length, IoMmuAccess));=0D
+ DEBUG ((DEBUG_VERBOSE," SecondLevelPagingEntry Base - 0x%x\n", SecondLe=
velPagingEntry));=0D
+=0D
+ if (BaseAddress !=3D ALIGN_VALUE(BaseAddress, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ if (Length !=3D ALIGN_VALUE(Length, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ while (Length !=3D 0) {=0D
+ PageEntry =3D GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagin=
gEntry, BaseAddress, mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAtt=
ribute);=0D
+ if (PageEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+ SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageAttribute);=
=0D
+ if (SplitAttribute =3D=3D PageNone) {=0D
+ ConvertSecondLevelPageEntryAttribute (VtdIndex, PageEntry, IoMmuAcce=
ss, &IsEntryModified);=0D
+ if (IsEntryModified) {=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ }=0D
+ //=0D
+ // Convert success, move to next=0D
+ //=0D
+ BaseAddress +=3D PageEntryLength;=0D
+ Length -=3D PageEntryLength;=0D
+ } else {=0D
+ Status =3D SplitSecondLevelPage (VtdIndex, PageEntry, PageAttribute,=
SplitAttribute);=0D
+ if (RETURN_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ //=0D
+ // Just split current page=0D
+ // Convert success in next around=0D
+ //=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (SecondLevelPagingEntry !=3D NULL) {=0D
+ Status =3D SetSecondLevelPagingAttribute (VtdIndex, DomainIdentifier, =
SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);=0D
+ }=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ EFI_STATUS Status;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+ UINTN PciDataIndex;=0D
+ UINT16 DomainIdentifier;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetAccessAttribute (S%04x B%02x D%02x F%02x) (0x%=
016lx - 0x%08x, %x)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function, BaseAddress, (UINTN)Length, IoMmuAccess));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"SetAccessAttribute - Pci device (S%04x B%02x D%02=
x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceData[PciDataIndex]=
.AccessCount++;=0D
+ //=0D
+ // DomainId should not be 0.=0D
+ //=0D
+ DomainIdentifier =3D (UINT16)(PciDataIndex + 1);=0D
+=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ if (ExtContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT3=
2) Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT3=
2) RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtC=
ontextEntry));=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
VtdIndex].ExtRootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=
=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtCont=
extEntry->Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry->Bits.S=
econdLevelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ if (ContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) =
Pt;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) =
RShiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*Context=
Entry));=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Vtd=
Index].RootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(Context=
Entry->Bits.SecondLevelPageTranslationPointerLo, ContextEntry->Bits.SecondL=
evelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Do not update FixedSecondLevelPagingEntry=0D
+ //=0D
+ if (SecondLevelPagingEntry !=3D mVtdUnitInformation[VtdIndex].FixedSecon=
dLevelPagingEntry) {=0D
+ Status =3D SetPageAttribute (=0D
+ VtdIndex,=0D
+ DomainIdentifier,=0D
+ SecondLevelPagingEntry,=0D
+ BaseAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR,"SetPageAttribute - %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ InvalidatePageEntry (VtdIndex);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"AlwaysEnablePageAttribute (S%04x B%02x D%02x F%02x)\=
n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Functio=
n));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"AlwaysEnablePageAttribute - Pci device (S%04x B%0=
2x D%02x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.De=
vice, SourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D=3D 0) =
{=0D
+ DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex));=
=0D
+ mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D CreateSe=
condLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCES=
S_WRITE, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ }=0D
+=0D
+ SecondLevelPagingEntry =3D mVtdUnitInformation[VtdIndex].FixedSecondLeve=
lPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32)=
Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32)=
RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdU=
nitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtCon=
textEntry));=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) Pt=
;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) RS=
hiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdUnit=
Information[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEn=
try));=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTableEx.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDx=
e/TranslationTableEx.c
new file mode 100644
index 000000000..c07afaf2b
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
TableEx.c
@@ -0,0 +1,108 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_=
ENTRY_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD=
_CONTEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].ExtRootEntryTable =3D (VTD_EXT_ROOT_ENTRY =
*)Buffer;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[Sour=
ceId.Index.RootIndex];=0D
+ if (ExtRootEntry->Bits.LowerPresent =3D=3D 0) {=0D
+ ExtRootEntry->Bits.LowerContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12);=0D
+ ExtRootEntry->Bits.LowerContextTablePointerHi =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 32);=0D
+ ExtRootEntry->Bits.LowerPresent =3D 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12) + 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerHi =3D (UINT32) RShiftU6=
4 (RShiftU64 ((UINT64)(UINTN)Buffer, 12) + 1, 20);=0D
+ ExtRootEntry->Bits.UpperPresent =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_AD=
DRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.Low=
erContextTablePointerHi) ;=0D
+ ExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.ContextIndex]=
;=0D
+ ExtContextEntry->Bits.TranslationType =3D 0;=0D
+ ExtContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ExtContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n", mVtdUnitInfor=
mation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId=
.Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+=0D
+=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Ext=
RootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdR=
eg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
new file mode 100644
index 000000000..dd0c49698
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
@@ -0,0 +1,757 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#define VTD_CAP_REG_NFR_MAX (256)=0D
+=0D
+UINTN mVtdUnitNumber =3D 0;=0D
+VTD_UNIT_INFORMATION *mVtdUnitInformation =3D NULL;=0D
+VTD_REGESTER_INFO *mVtdRegsInfoBuffer =3D NULL;=0D
+=0D
+BOOLEAN mVtdEnabled;=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *)Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_IQA_REG IqaReg;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[VtdIndex];=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ if (VtdUnitInfo->VerReg.Bits.Major <=3D 5) {=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for eng=
ine [%d]\n", VtdIndex));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ECapReg.Bits.QI =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations i=
nterface for engine [%d]\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 1;=0D
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n=
", VtdIndex));=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ if ((Reg32 & B_GSTS_REG_QIES) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n"));=
=0D
+=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitBaseAddress);=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the Invalidation Queue Tail Register to zero.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);=0D
+=0D
+ //=0D
+ // Setup the IQ address, size and descriptor width through the Invalidat=
ion Queue Address Register=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ VtdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <=
< (VTD_INVALIDATION_QUEUE_SIZE + 7)));=0D
+ VtdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VtdUni=
tInfo->QiDescBufferSize));=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"))=
;=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ERROR_OUT=
_OF_RESOURCES, VtdUnitBaseAddress);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VtdUnitInfo=
->QiDescBufferSize));=0D
+ //=0D
+ // 4KB Aligned address=0D
+ //=0D
+ IqaReg.Uint64 =3D (UINT64) (UINTN) VtdUnitInfo->QiDescBuffer;=0D
+ IqaReg.Bits.DW =3D VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH;=0D
+ IqaReg.Bits.QS =3D VTD_INVALIDATION_QUEUE_SIZE;=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ DEBUG ((DEBUG_INFO, "IQA_REG =3D 0x%lx, IQH_REG =3D 0x%lx\n", IqaReg.Uin=
t64, MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));=0D
+=0D
+ //=0D
+ // Enable the queued invalidation interface through the Global Command R=
egister.=0D
+ // When enabled, hardware sets the QIES field in the Global Status Regis=
ter.=0D
+ //=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 |=3D B_GMCD_REG_QIE;=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG =3D =
0x%x\n", Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ENABLE, VtdUn=
itBaseAddress);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+SubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN QI_256_DESC *Desc=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_REGESTER_QI_INFO RegisterQi;=0D
+=0D
+ Status =3D VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress,=
Desc, FALSE);=0D
+ if (Status =3D=3D EFI_DEVICE_ERROR) {=0D
+ RegisterQi.BaseAddress =3D VtdUnitBaseAddress;=0D
+ RegisterQi.FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG=
);;=0D
+ RegisterQi.IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_R=
EG);=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_QI, &Register=
Qi, sizeof (VTD_REGESTER_QI_INFO));=0D
+=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, RegisterQi.FstsReg & (B_=
FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE));=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ R_CCMD_REG);=0D
+ if ((Reg64 & B_CCMD_REG_ICC) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC i=
s set for VTD(%d)\n",VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));=0D
+ Reg64 |=3D (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD=
_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + R_CCMD_REG);=0D
+ } while ((Reg64 & B_CCMD_REG_ICC) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC=
_GRAN(1) | QI_CC_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=0D
+ if ((Reg64 & B_IOTLB_REG_IVT) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set =
for VTD(%d)\n", VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));=0D
+ Reg64 |=3D (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdU=
nitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=
=0D
+ } while ((Reg64 & B_IOTLB_REG_IVT) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtd=
UnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVt=
dUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TY=
PE;=0D
+ QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0=
);=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (!mVtdEnabled) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext) {=0D
+ InvalidateContextCache (VtdIndex);=0D
+ }=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN DomainNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ if (mVtdRegsInfoBuffer =3D=3D NULL) {=0D
+ mVtdRegsInfoBuffer =3D AllocateZeroPool (sizeof (VTD_REGESTER_INFO) + =
sizeof (VTD_UINT128) * VTD_CAP_REG_NFR_MAX);=0D
+ ASSERT (mVtdRegsInfoBuffer !=3D NULL);=0D
+ }=0D
+=0D
+ //=0D
+ // Dump VTd error before DXE phase=0D
+ //=0D
+ DumpVtdIfError ();=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));=0D
+ mVtdUnitInformation[Index].VerReg.Uint32 =3D MmioRead32 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_VER_REG);=0D
+ DumpVtdVerRegs (&mVtdUnitInformation[Index].VerReg);=0D
+ mVtdUnitInformation[Index].CapReg.Uint64 =3D MmioRead64 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_CAP_REG);=0D
+ DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);=0D
+ mVtdUnitInformation[Index].ECapReg.Uint64 =3D MmioRead64 (mVtdUnitInfo=
rmation[Index].VtdUnitBaseAddress + R_ECAP_REG);=0D
+ DumpVtdECapRegs (&mVtdUnitInformation[Index].ECapReg);=0D
+=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) =3D=3D 0) {=
=0D
+ DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !=
!!!\n", Index));=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) =3D=
=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on V=
TD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));=0D
+ return ;=0D
+ }=0D
+=0D
+ DomainNumber =3D (UINTN)1 << (UINT8)((UINTN)mVtdUnitInformation[Index]=
.CapReg.Bits.ND * 2 + 4);=0D
+ if (mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumber >=3D=
DomainNumber) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >=3D DomainNumber(=
0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumbe=
r, DomainNumber));=0D
+ return ;=0D
+ }=0D
+=0D
+ Status =3D PerpareCacheInvalidationInterface(Index);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT(FALSE);=0D
+ return;=0D
+ }=0D
+ }=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Disable PMR in all VTd engine.=0D
+**/=0D
+VOID=0D
+DisablePmr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DisablePmr\n"));=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ Status =3D VtdLibDisablePmr (mVtdUnitInformation[Index].VtdUnitBaseAdd=
ress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_PMR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, Status);=0D
+ }=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Update Root Table Address Register=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] EnableADM TRUE - Enable ADM in TTM bits=0D
+**/=0D
+VOID=0D
+UpdateRootTableAddressRegister (=0D
+ IN UINTN VtdIndex,=0D
+ IN BOOLEAN EnableADM=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D NULL) {=0D
+ DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Vt=
dIndex].ExtRootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTab=
le | (EnableADM ? V_RTADDR_REG_TTM_ADM : BIT11);=0D
+ } else {=0D
+ DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[VtdIn=
dex].RootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable =
| (EnableADM ? V_RTADDR_REG_TTM_ADM : 0);=0D
+ }=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR=
_REG, Reg64);=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ BOOLEAN TEWasEnabled;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitBaseAddress =3D mVtdUnitInformation[Index].VtdUnitBaseAddress;=
=0D
+ DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] BAR [0x%x]\n", =
Index, VtdUnitBaseAddress));=0D
+=0D
+ //=0D
+ // Check TE was enabled or not.=0D
+ //=0D
+ TEWasEnabled =3D ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GS=
TS_REG_TE) =3D=3D B_GSTS_REG_TE);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ //=0D
+ // For implementations reporting Enhanced SRTP Support (ESRTPS) fiel=
d as=0D
+ // Clear in the Capability register, software must not modify this f=
ield while=0D
+ // DMA remapping is active (TES=3D1 in Global Status register).=0D
+ //=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable ADM=0D
+ //=0D
+ UpdateRootTableAddressRegister (Index, TRUE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+=0D
+ DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_T=
E);=0D
+=0D
+ } else {=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ InvalidateContextCache (Index);=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ InvalidateIOTLB (Index);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_ENABLE_DMAR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, 0);=0D
+ }=0D
+=0D
+ //=0D
+ // Need disable PMR, since we already setup translation table.=0D
+ //=0D
+ DisablePmr ();=0D
+=0D
+ mVtdEnabled =3D TRUE;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN SubIndex;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+=0D
+ VtdLibDisableDmar (VtdUnitInfo->VtdUnitBaseAddress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_DMAR, VtdUnitInfo->VtdUnitBaseAddre=
ss, 0);=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation !=3D 0) {=0D
+ //=0D
+ // Disable queued invalidation interface.=0D
+ //=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitInfo->VtdUnitBaseAd=
dress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_DISABLE, =
VtdUnitInfo->VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Free descriptor queue memory=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer !=3D NULL) {=0D
+ FreePages(VtdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VtdUnitInf=
o->QiDescBufferSize));=0D
+ VtdUnitInfo->QiDescBuffer =3D NULL;=0D
+ VtdUnitInfo->QiDescBufferSize =3D 0;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ }=0D
+ }=0D
+=0D
+ mVtdEnabled =3D FALSE;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+ DEBUG((DEBUG_INFO, "engine [%d] access\n", Index));=0D
+ for (SubIndex =3D 0; SubIndex < VtdUnitInfo->PciDeviceInfo->PciDeviceD=
ataNumber; SubIndex++) {=0D
+ DEBUG ((DEBUG_INFO, " PCI S%04X B%02x D%02x F%02x - %d\n",=0D
+ VtdUnitInfo->Segment,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Bus,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Device,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Function,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].AccessCount=0D
+ ));=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, " VerReg - 0x%x\n", VerReg->Uint32));=0D
+ DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major));=0D
+ DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ )=0D
+{=0D
+ DEBUG((DEBUG_INFO, " CapReg - 0x%x\n", CapReg->Uint64));=0D
+ DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND));=0D
+ DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL));=0D
+ DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF));=0D
+ DEBUG((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR));=0D
+ DEBUG((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR));=0D
+ DEBUG((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM));=0D
+ DEBUG((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW));=0D
+ DEBUG((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW));=0D
+ DEBUG((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR));=0D
+ DEBUG((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO));=0D
+ DEBUG((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS));=0D
+ DEBUG((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI));=0D
+ DEBUG((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR));=0D
+ DEBUG((DEBUG_INFO, " MAMV - 0x%x\n", CapReg->Bits.MAMV));=0D
+ DEBUG((DEBUG_INFO, " DWD - 0x%x\n", CapReg->Bits.DWD));=0D
+ DEBUG((DEBUG_INFO, " DRD - 0x%x\n", CapReg->Bits.DRD));=0D
+ DEBUG((DEBUG_INFO, " FL1GP - 0x%x\n", CapReg->Bits.FL1GP));=0D
+ DEBUG((DEBUG_INFO, " PI - 0x%x\n", CapReg->Bits.PI));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd extended capability registers.=0D
+=0D
+ @param[in] ECapReg The extended capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdECapRegs (=0D
+ IN VTD_ECAP_REG *ECapReg=0D
+ )=0D
+{=0D
+ DEBUG((DEBUG_INFO, " ECapReg - 0x%lx\n", ECapReg->Uint64));=0D
+ DEBUG((DEBUG_INFO, " C - 0x%x\n", ECapReg->Bits.C));=0D
+ DEBUG((DEBUG_INFO, " QI - 0x%x\n", ECapReg->Bits.QI));=0D
+ DEBUG((DEBUG_INFO, " DT - 0x%x\n", ECapReg->Bits.DT));=0D
+ DEBUG((DEBUG_INFO, " IR - 0x%x\n", ECapReg->Bits.IR));=0D
+ DEBUG((DEBUG_INFO, " EIM - 0x%x\n", ECapReg->Bits.EIM));=0D
+ DEBUG((DEBUG_INFO, " PT - 0x%x\n", ECapReg->Bits.PT));=0D
+ DEBUG((DEBUG_INFO, " SC - 0x%x\n", ECapReg->Bits.SC));=0D
+ DEBUG((DEBUG_INFO, " IRO - 0x%x\n", ECapReg->Bits.IRO));=0D
+ DEBUG((DEBUG_INFO, " MHMV - 0x%x\n", ECapReg->Bits.MHMV));=0D
+ DEBUG((DEBUG_INFO, " MTS - 0x%x\n", ECapReg->Bits.MTS));=0D
+ DEBUG((DEBUG_INFO, " NEST - 0x%x\n", ECapReg->Bits.NEST));=0D
+ DEBUG((DEBUG_INFO, " PASID - 0x%x\n", ECapReg->Bits.PASID));=0D
+ DEBUG((DEBUG_INFO, " PRS - 0x%x\n", ECapReg->Bits.PRS));=0D
+ DEBUG((DEBUG_INFO, " ERS - 0x%x\n", ECapReg->Bits.ERS));=0D
+ DEBUG((DEBUG_INFO, " SRS - 0x%x\n", ECapReg->Bits.SRS));=0D
+ DEBUG((DEBUG_INFO, " NWFS - 0x%x\n", ECapReg->Bits.NWFS));=0D
+ DEBUG((DEBUG_INFO, " EAFS - 0x%x\n", ECapReg->Bits.EAFS));=0D
+ DEBUG((DEBUG_INFO, " PSS - 0x%x\n", ECapReg->Bits.PSS));=0D
+ DEBUG((DEBUG_INFO, " SMTS - 0x%x\n", ECapReg->Bits.SMTS));=0D
+ DEBUG((DEBUG_INFO, " ADMS - 0x%x\n", ECapReg->Bits.ADMS));=0D
+ DEBUG((DEBUG_INFO, " PDS - 0x%x\n", ECapReg->Bits.PDS));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegs (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ VTD_REGESTER_INFO *VtdRegInfo;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_CAP_REG CapReg;=0D
+=0D
+ if (mVtdRegsInfoBuffer =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VtdRegInfo =3D mVtdRegsInfoBuffer;=0D
+ VtdRegInfo->BaseAddress =3D VtdUnitBaseAddress;=0D
+ VtdRegInfo->VerReg =3D MmioRead32 (VtdUnitBaseAddress + R_VER_REG);=
=0D
+ VtdRegInfo->CapReg =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=
=0D
+ VtdRegInfo->EcapReg =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG)=
;=0D
+ VtdRegInfo->GstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG)=
;=0D
+ VtdRegInfo->RtaddrReg =3D MmioRead64 (VtdUnitBaseAddress + R_RTADDR_RE=
G);=0D
+ VtdRegInfo->CcmdReg =3D MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG)=
;=0D
+ VtdRegInfo->FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG)=
;=0D
+ VtdRegInfo->FectlReg =3D MmioRead32 (VtdUnitBaseAddress + R_FECTL_REG=
);=0D
+ VtdRegInfo->FedataReg =3D MmioRead32 (VtdUnitBaseAddress + R_FEDATA_RE=
G);=0D
+ VtdRegInfo->FeaddrReg =3D MmioRead32 (VtdUnitBaseAddress + R_FEADDR_RE=
G);=0D
+ VtdRegInfo->FeuaddrReg =3D MmioRead32 (VtdUnitBaseAddress + R_FEUADDR_R=
EG);=0D
+ VtdRegInfo->IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_RE=
G);=0D
+=0D
+ CapReg.Uint64 =3D VtdRegInfo->CapReg;=0D
+ for (VtdRegInfo->FrcdRegNum =3D 0; VtdRegInfo->FrcdRegNum < (UINT16) Cap=
Reg.Bits.NFR + 1; VtdRegInfo->FrcdRegNum++) {=0D
+ VtdRegInfo->FrcdReg[VtdRegInfo->FrcdRegNum].Uint64Lo =3D MmioRead64 (V=
tdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (VtdRegInfo->FrcdRegNum * 16)=
+ R_FRCD_REG));=0D
+ VtdRegInfo->FrcdReg[VtdRegInfo->FrcdRegNum].Uint64Hi =3D MmioRead64 (V=
tdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (VtdRegInfo->FrcdRegNum * 16)=
+ R_FRCD_REG + sizeof(UINT64)));=0D
+ }=0D
+=0D
+ ECapReg.Uint64 =3D VtdRegInfo->EcapReg;=0D
+ VtdRegInfo->IvaReg =3D MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IR=
O * 16) + R_IVA_REG);=0D
+ VtdRegInfo->IotlbReg =3D MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.=
IRO * 16) + R_IOTLB_REG);=0D
+=0D
+ DEBUG((DEBUG_INFO, "#### DumpVtdRegs(0x%016lx) Begin ####\n", VtdUnitBas=
eAddress));=0D
+=0D
+ VtdLibDumpVtdRegsAll (NULL, NULL, VtdRegInfo);=0D
+=0D
+ DEBUG((DEBUG_INFO, "#### DumpVtdRegs(0x%016lx) End ####\n", VtdUnitBaseA=
ddress));=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_REGISTER, VTDLOG_REGISTER_ALL, (VOID *) V=
tdRegInfo, sizeof (VTD_REGESTER_INFO) + sizeof (VTD_UINT128) * (VtdRegInfo-=
FrcdRegNum - 1));=0D+}=0D
+=0D
+/**=0D
+ Dump VTd registers for all VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegsAll (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ DumpVtdRegs (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Num;=0D
+ UINTN Index;=0D
+ VTD_FRCD_REG FrcdReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ UINT32 Reg32;=0D
+ BOOLEAN HasError;=0D
+=0D
+ for (Num =3D 0; Num < mVtdUnitNumber; Num++) {=0D
+ HasError =3D FALSE;=0D
+ Reg32 =3D MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_=
FSTS_REG);=0D
+ if (Reg32 !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+ Reg32 =3D MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_=
FECTL_REG);=0D
+ if ((Reg32 & BIT30) !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddr=
ess + R_CAP_REG);=0D
+ for (Index =3D 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[0] =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnitBa=
seAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnitBa=
seAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UI=
NT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+ }=0D
+=0D
+ if (HasError) {=0D
+ REPORT_STATUS_CODE (EFI_ERROR_CODE, PcdGet32 (PcdErrorCodeVTdError))=
;=0D
+ DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));=0D
+ DumpVtdRegs (Num);=0D
+ DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));=0D
+ //=0D
+ // Clear=0D
+ //=0D
+ for (Index =3D 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (mVtdUnitInformation[Num].VtdUnit=
BaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(=
UINT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ //=0D
+ // Software writes the value read from this field (F) to Clear i=
t.=0D
+ //=0D
+ MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((Cap=
Reg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.U=
int64[1]);=0D
+ }=0D
+ }=0D
+ MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_RE=
G, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG));=
=0D
+ }=0D
+ }=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Dmar=
Table.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/DmarTab=
le.c
new file mode 100644
index 000000000..5672f4014
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/DmarTable.c
@@ -0,0 +1,301 @@
+/** @file=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/HobLib.h>=0D
+#include <Library/PciSegmentLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <IndustryStandard/Pci.h>=0D
+#include <Protocol/IoMmu.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+/**=0D
+ Dump DMAR DeviceScopeEntry.=0D
+=0D
+ @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry=0D
+**/=0D
+VOID=0D
+DumpDmarDeviceScopeEntry (=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry=0D
+ )=0D
+{=0D
+ UINTN PciPathNumber;=0D
+ UINTN PciPathIndex;=0D
+ EFI_ACPI_DMAR_PCI_PATH *PciPath;=0D
+=0D
+ if (DmarDeviceScopeEntry =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " * DMA-Remapping Device Scope Entry Structure =
*\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ (sizeof (UINTN) =3D=3D sizeof (UINT64)) ?=0D
+ " DMAR Device Scope Entry address ...................... 0x%016lx\n=
" :=0D
+ " DMAR Device Scope Entry address ...................... 0x%08x\n",=
=0D
+ DmarDeviceScopeEntry=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Device Scope Entry Type ............................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Type=0D
+ ));=0D
+ switch (DmarDeviceScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " PCI Endpoint Device\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " PCI Sub-hierachy\n"=0D
+ ));=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................. 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Length=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Enumeration ID ..................................... 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->EnumerationId=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Starting Bus Number ................................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->StartBusNumber=0D
+ ));=0D
+=0D
+ PciPathNumber =3D (DmarDeviceScopeEntry->Length - sizeof (EFI_ACPI_DMAR_=
DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof (EFI_ACPI_DMAR_PCI_PATH);=0D
+ PciPath =3D (EFI_ACPI_DMAR_PCI_PATH *) (DmarDeviceScopeEntry + 1);=0D
+ for (PciPathIndex =3D 0; PciPathIndex < PciPathNumber; PciPathIndex++) {=
=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Device ............................................. 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Device=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Function ........................................... 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Function=0D
+ ));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n\n"=0D
+ ));=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR DRHD table.=0D
+=0D
+ @param[in] Drhd DMAR DRHD table=0D
+**/=0D
+VOID=0D
+DumpDmarDrhd (=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN DrhdLen;=0D
+=0D
+ if (Drhd =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " * DMA-Remapping Hardware Definition Structure =
*\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ (sizeof (UINTN) =3D=3D sizeof (UINT64)) ?=0D
+ " DRHD address ........................................... 0x%016lx\n=
" :=0D
+ " DRHD address ........................................... 0x%08x\n",=
=0D
+ Drhd=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Drhd->Header.Type=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Drhd->Header.Length=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Drhd->Flags=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " INCLUDE_PCI_ALL .................................... 0x%02x\n",=
=0D
+ Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Drhd->SegmentNumber=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Register Base Address ................................ 0x%016lx\n=
",=0D
+ Drhd->RegisterBaseAddress=0D
+ ));=0D
+=0D
+ DrhdLen =3D Drhd->Header.Length - sizeof (EFI_ACPI_DMAR_DRHD_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Drhd + 1);=0D
+ while (DrhdLen > 0) {=0D
+ DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);=0D
+ DrhdLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*) ((UINTN) DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+DumpAcpiDMAR (=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ INTN DmarLen;=0D
+=0D
+ if (Dmar =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "* DMAR Table =
*\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ (sizeof (UINTN) =3D=3D sizeof (UINT64)) ?=0D
+ "DMAR address ............................................. 0x%016lx\n=
" :=0D
+ "DMAR address ............................................. 0x%08x\n",=
=0D
+ Dmar=0D
+ ));=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Table Contents:\n"=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Host Address Width ................................... 0x%02x\n",=
=0D
+ Dmar->HostAddressWidth=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Dmar->Flags=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " INTR_REMAP ......................................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT=0D
+ ));=0D
+ DEBUG ((DEBUG_INFO,=0D
+ " DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG=0D
+ ));=0D
+=0D
+ DmarLen =3D Dmar->Header.Length - sizeof (EFI_ACPI_DMAR_HEADER);=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) (Dmar + 1);=0D
+ while (DmarLen > 0) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarLen -=3D DmarHeader->Length;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader =
+ DmarHeader->Length);=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n\n"=0D
+ ));=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @param[in] AcpiDmarTable DMAR ACPI table=0D
+ @param[in] Callback Callback function for handle DRHD=0D
+ @param[in] Context Callback function Context=0D
+=0D
+ @return the VTd engine number.=0D
+=0D
+**/=0D
+UINTN=0D
+ParseDmarAcpiTableDrhd (=0D
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,=0D
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ UINTN VtdIndex;=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTabl=
e + 1));=0D
+=0D
+ while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ if (Callback !=3D NULL) {=0D
+ Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHea=
der);=0D
+ }=0D
+ VtdIndex++;=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader =
+ DmarHeader->Length);=0D
+ }=0D
+=0D
+ return VtdIndex;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/I=
ntelVTdCorePei.c
new file mode 100644
index 000000000..0160c3604
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.c
@@ -0,0 +1,1099 @@
+/** @file=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/PeiServicesLib.h>=0D
+#include <Library/HobLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <Ppi/IoMmu.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Ppi/MemoryDiscovered.h>=0D
+#include <Ppi/EndOfPeiPhase.h>=0D
+#include <Guid/VtdPmrInfoHob.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+#define VTD_UNIT_MAX 64=0D
+=0D
+EFI_GUID mVTdInfoGuid =3D {=0D
+ 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x=
82 }=0D
+};=0D
+=0D
+EFI_GUID mDmaBufferInfoGuid =3D {=0D
+ 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, =
0x39 }=0D
+};=0D
+=0D
+#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ EDKII_IOMMU_OPERATION Operation;=0D
+ UINTN NumberOfBytes;=0D
+ EFI_PHYSICAL_ADDRESS HostAddress;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+} MAP_INFO;=0D
+=0D
+/**=0D
+ Allocate memory buffer for VTd log events.=0D
+=0D
+ @param[in] MemorySize Required memory buffer size.=0D
+=0D
+ @retval Buffer address=0D
+=0D
+**/=0D
+UINT8 *=0D
+EFIAPI=0D
+VTdLogAllocMemory (=0D
+ IN CONST UINT32 MemorySize=0D
+ )=0D
+{=0D
+ VOID *HobPtr;=0D
+ VTDLOG_PEI_BUFFER_HOB *BufferHob;=0D
+ UINT8 *ReturnBuffer;=0D
+=0D
+ ReturnBuffer =3D NULL;=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ BufferHob =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ if (BufferHob->PostMemBuffer !=3D 0) {=0D
+ //=0D
+ // Post-memory phase=0D
+ //=0D
+ if ((BufferHob->PostMemBufferUsed + MemorySize) < PcdGet32 (PcdVTdPe=
iPostMemLogBufferSize)) {=0D
+ ReturnBuffer =3D &((UINT8 *) (UINTN) BufferHob->PostMemBuffer)[Buf=
ferHob->PostMemBufferUsed];=0D
+ BufferHob->PostMemBufferUsed +=3D MemorySize;=0D
+ } else {=0D
+ BufferHob->VtdLogPeiError |=3D VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return ReturnBuffer;=0D
+}=0D
+=0D
+/**=0D
+ Add the VTd log event in post memory phase.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM *Item;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_PEI_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ Item =3D (VTDLOG_EVENT_2PARAM *) VTdLogAllocMemory (sizeof (VTDLOG_EVENT=
_2PARAM));=0D
+ if (Item !=3D NULL) {=0D
+ Item->Data1 =3D Data1;=0D
+ Item->Data2 =3D Data2;=0D
+ Item->Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item->Header.LogType =3D (UINT64) (1 << EventType);=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_CONTEXT *Item;=0D
+ UINT32 EventSize;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_PEI_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ EventSize =3D sizeof (VTDLOG_EVENT_CONTEXT) + DataSize - 1;=0D
+=0D
+ Item =3D (VTDLOG_EVENT_CONTEXT *) VTdLogAllocMemory (EventSize);=0D
+ if (Item !=3D NULL) {=0D
+ Item->Param =3D Param;=0D
+ CopyMem (Item->Data, Data, DataSize);=0D
+=0D
+ Item->Header.DataSize =3D EventSize;=0D
+ Item->Header.LogType =3D (UINT64) (1 << EventType);=0D
+ Item->Header.Timestamp =3D AsmReadTsc (); =0D
+ }=0D
+}=0D
+/**=0D
+ Add the VTd log event in pre-memory phase.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Mode Pre-memory DMA protection mode.=0D
+ @param[in] Status Status=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddPreMemoryEvent (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT8 Mode,=0D
+ IN UINT8 Status=0D
+ )=0D
+{=0D
+ VTDLOG_PEI_BUFFER_HOB *BufferHob;=0D
+ VOID *HobPtr;=0D
+ UINT8 Index;=0D
+=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ BufferHob =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ for (Index =3D 0; Index < VTD_LOG_PEI_PRE_MEM_BAR_MAX; Index++) {=0D
+ if (BufferHob->PreMemInfo[Index].Mode =3D=3D VTD_LOG_PEI_PRE_MEM_NOT=
_USED) {=0D
+ //=0D
+ // Found a free posttion=0D
+ //=0D
+ BufferHob->PreMemInfo[Index].BarAddress =3D (UINT32) VtdUnitBaseAd=
dress;=0D
+ BufferHob->PreMemInfo[Index].Mode =3D Mode;=0D
+ BufferHob->PreMemInfo[Index].Status =3D Status;=0D
+ break;=0D
+ }=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Initializes the VTd Log.=0D
+=0D
+ @param[in] MemoryInitialized TRUE: It is post-memory phase=0D
+ FALSE: It is pre-memory phase=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogInitialize(=0D
+ BOOLEAN MemoryInitialized=0D
+ )=0D
+{=0D
+ VTDLOG_PEI_BUFFER_HOB *BufferHob;=0D
+ VOID *HobPtr;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) > 0) {=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr =3D=3D NULL) {=0D
+ BufferHob =3D BuildGuidHob (&gVTdLogBufferHobGuid, sizeof (VTDLOG_PE=
I_BUFFER_HOB));=0D
+ ASSERT (BufferHob !=3D NULL);=0D
+=0D
+ ZeroMem (BufferHob, sizeof (VTDLOG_PEI_BUFFER_HOB));=0D
+ } else {=0D
+ BufferHob =3D GET_GUID_HOB_DATA (HobPtr);=0D
+ }=0D
+=0D
+ if (MemoryInitialized) {=0D
+ if ((BufferHob->PostMemBuffer =3D=3D 0) && (PcdGet32 (PcdVTdPeiPostM=
emLogBufferSize) > 0)) {=0D
+ BufferHob->PostMemBufferUsed =3D 0;=0D
+ BufferHob->PostMemBuffer =3D (UINTN) AllocateAlignedPages (EFI_SIZ=
E_TO_PAGES (PcdGet32 (PcdVTdPeiPostMemLogBufferSize)), sizeof (UINT8));=0D
+ }=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU PPI exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ @param[in] This The PPI instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA acces=
s request.=0D
+ @param[in] Mapping The mapping value returned from Map().=
=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory =
range specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was return=
ed by Map().=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combi=
nation of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not sup=
ported by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory =
range specified by Mapping.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availab=
le to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error whi=
le attempting the operation.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuSetAttribute (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN VOID *Mapping,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ //=0D
+ // check and clear VTd error=0D
+ //=0D
+ DumpVtdIfError ();=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuSetAttribute:\n"));=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuSetAttribute: DmaBufferCurrentTop =3D=3D =
0\n"));=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] Operation Indicates if the bus master is going t=
o read or write to system memory.=0D
+ @param [in] HostAddress The system memory address to map to th=
e PCI controller.=0D
+ @param [in] [out] NumberOfBytes On input the number of bytes to map. O=
n output the number of bytes=0D
+ that were mapped.=0D
+ @param [out] DeviceAddress The resulting map address for the bus =
master PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param [out] Mapping A resulting value to pass to Unmap().=
=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned =
NumberOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a =
common buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due=
to a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the =
requested address.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuMap (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %=
x\n", HostAddress, *NumberOfBytes));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+ DEBUG ((DEBUG_INFO, " Operation - %x\n", Operation));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64) {=0D
+ *DeviceAddress =3D (UINTN) HostAddress;=0D
+ *Mapping =3D NULL;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ Length =3D *NumberOfBytes + sizeof (MAP_INFO);=0D
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBuff=
erCurrentBottom) {=0D
+ DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));=0D
+ VTdLogAddEvent (VTDLOG_PEI_VTD_ERROR, VTD_LOG_PEI_VTD_ERROR_PPI_MAP, L=
ength);=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ *DeviceAddress =3D DmaBufferInfo->DmaBufferCurrentBottom;=0D
+ DmaBufferInfo->DmaBufferCurrentBottom +=3D Length;=0D
+=0D
+ MapInfo =3D (VOID *) (UINTN) (*DeviceAddress + *NumberOfBytes);=0D
+ MapInfo->Signature =3D MAP_INFO_SIGNATURE;=0D
+ MapInfo->Operation =3D Operation;=0D
+ MapInfo->NumberOfBytes =3D *NumberOfBytes;=0D
+ MapInfo->HostAddress =3D (UINTN) HostAddress;=0D
+ MapInfo->DeviceAddress =3D *DeviceAddress;=0D
+ *Mapping =3D MapInfo;=0D
+ DEBUG ((DEBUG_INFO, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Opera=
tion, (UINTN) *DeviceAddress, MapInfo));=0D
+=0D
+ //=0D
+ // If this is a read operation from the Bus Master's point of view,=0D
+ // then copy the contents of the real buffer into the mapped buffer=0D
+ // so the Bus Master can read the contents of the real buffer.=0D
+ //=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterRead ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterRead64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_PPI_MAP, (UINT64) HostAddress, Length);=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] Mapping The mapping value returned from Map().=
=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was return=
ed by Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the targ=
et system memory.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuUnmap (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN VOID *Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ MapInfo =3D Mapping;=0D
+ ASSERT (MapInfo->Signature =3D=3D MAP_INFO_SIGNATURE);=0D
+ DEBUG ((DEBUG_INFO, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n",=
MapInfo->Operation, (UINTN) MapInfo->DeviceAddress, MapInfo->NumberOfBytes=
));=0D
+=0D
+ //=0D
+ // If this is a write operation from the Bus Master's point of view,=0D
+ // then copy the contents of the mapped buffer into the real buffer=0D
+ // so the processor can read the contents of the real buffer.=0D
+ //=0D
+ if (MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite ||=0D
+ MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ Length =3D MapInfo->NumberOfBytes + sizeof (MAP_INFO);=0D
+ if (DmaBufferInfo->DmaBufferCurrentBottom =3D=3D MapInfo->DeviceAddress =
+ Length) {=0D
+ DmaBufferInfo->DmaBufferCurrentBottom -=3D Length;=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] MemoryType The type of memory to allocate, EfiBoo=
tServicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param [in] Pages The number of pages to allocate.=0D
+ @param [in] [out] HostAddress A pointer to store the base system mem=
ory address of the=0D
+ allocated range.=0D
+ @param [in] Attributes The requested bit mask of attributes f=
or the allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were alloca=
ted.=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only le=
gal attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED an=
d DUAL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocate=
d.=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ )=0D
+{=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ Length =3D EFI_PAGES_TO_SIZE (Pages);=0D
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBuff=
erCurrentBottom) {=0D
+ DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));=0D
+ VTdLogAddEvent (VTDLOG_PEI_VTD_ERROR, VTD_LOG_PEI_VTD_ERROR_PPI_ALLOC,=
Length);=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ *HostAddress =3D (VOID *) (UINTN) (DmaBufferInfo->DmaBufferCurrentTop - =
Length);=0D
+ DmaBufferInfo->DmaBufferCurrentTop -=3D Length;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAdd=
ress));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_PPI_ALLOC_BUFFER, (UINT64) (*HostAddress), Le=
ngth);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param [in] This The PPI instance pointer.=0D
+ @param [in] Pages The number of pages to free.=0D
+ @param [in] HostAddress The base system memory address of the =
allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=
=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddr=
ess and Pages=0D
+ was not allocated with AllocateBuffer(=
).=0D
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but D=
MA buffer are=0D
+ not available to be allocated yet.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+PeiIoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PPI *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ )=0D
+{=0D
+ UINTN Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA (Hob);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", P=
ages, HostAddress));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBu=
fferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->Dm=
aBufferCurrentBottom));=0D
+=0D
+ if (DmaBufferInfo->DmaBufferCurrentTop =3D=3D 0) {=0D
+ return EFI_NOT_AVAILABLE_YET;=0D
+ }=0D
+=0D
+ Length =3D EFI_PAGES_TO_SIZE (Pages);=0D
+ if ((UINTN)HostAddress =3D=3D DmaBufferInfo->DmaBufferCurrentTop) {=0D
+ DmaBufferInfo->DmaBufferCurrentTop +=3D Length;=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+EDKII_IOMMU_PPI mIoMmuPpi =3D {=0D
+ EDKII_IOMMU_PPI_REVISION,=0D
+ PeiIoMmuSetAttribute,=0D
+ PeiIoMmuMap,=0D
+ PeiIoMmuUnmap,=0D
+ PeiIoMmuAllocateBuffer,=0D
+ PeiIoMmuFreeBuffer,=0D
+};=0D
+=0D
+CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList =3D {=0D
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,=0D
+ &gEdkiiIoMmuPpiGuid,=0D
+ (VOID *) &mIoMmuPpi=0D
+};=0D
+=0D
+/**=0D
+ Get ACPI DMAT Table from EdkiiVTdInfo PPI=0D
+=0D
+ @retval Address ACPI DMAT Table address=0D
+ @retval NULL Failed to get ACPI DMAT Table=0D
+**/=0D
+EFI_ACPI_DMAR_HEADER * GetAcpiDmarTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+=0D
+ //=0D
+ // Get the DMAR table=0D
+ //=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEdkiiVTdInfoPpiGuid,=0D
+ 0,=0D
+ NULL,=0D
+ (VOID **)&AcpiDmarTable=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "Fail to get ACPI DMAR Table : %r\n", Status));=0D
+ AcpiDmarTable =3D NULL;=0D
+ } else {=0D
+ VtdLibDumpAcpiDmarDrhd (NULL, NULL, AcpiDmarTable);=0D
+ }=0D
+=0D
+ return AcpiDmarTable;=0D
+}=0D
+=0D
+/**=0D
+ Get the VTd engine context information hob.=0D
+=0D
+ @retval The VTd engine context information.=0D
+=0D
+**/=0D
+VTD_INFO *=0D
+GetVTdInfoHob (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VOID *Hob;=0D
+ VTD_INFO *VTdInfo;=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mVTdInfoGuid);=0D
+ if (Hob =3D=3D NULL) {=0D
+ VTdInfo =3D BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO));=0D
+ if (VTdInfo !=3D NULL) {=0D
+ ZeroMem (VTdInfo, sizeof (VTD_INFO));=0D
+ }=0D
+ } else {=0D
+ VTdInfo =3D GET_GUID_HOB_DATA(Hob);=0D
+ }=0D
+ return VTdInfo;=0D
+}=0D
+=0D
+/**=0D
+ Callback function of parse DMAR DRHD table in pre-memory phase.=0D
+=0D
+ @param [in] [out] Context Callback function context.=0D
+ @param [in] VTdIndex The VTd engine index.=0D
+ @param [in] DmarDrhd The DRHD table.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessDhrdPreMemory (=0D
+ IN OUT VOID *Context,=0D
+ IN UINTN VTdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, DmarD=
rhd->RegisterBaseAddress));=0D
+=0D
+ EnableVTdTranslationProtectionBlockDma ((UINTN) DmarDrhd->RegisterBaseAd=
dress);=0D
+}=0D
+=0D
+/**=0D
+ Callback function of parse DMAR DRHD table in post memory phase.=0D
+=0D
+ @param [in] [out] Context Callback function context.=0D
+ @param [in] VTdIndex The VTd engine index.=0D
+ @param [in] DmarDrhd The DRHD table.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessDrhdPostMemory (=0D
+ IN OUT VOID *Context,=0D
+ IN UINTN VTdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+ UINTN Index;=0D
+=0D
+ VtdUnitInfo =3D (VTD_UNIT_INFO *) Context;=0D
+=0D
+ if (DmarDrhd->RegisterBaseAddress =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO,"VTd Base Address is 0\n"));=0D
+ ASSERT (FALSE);=0D
+ return;=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < VTD_UNIT_MAX; Index++) {=0D
+ if (VtdUnitInfo[Index].VtdUnitBaseAddress =3D=3D DmarDrhd->RegisterBas=
eAddress) {=0D
+ DEBUG ((DEBUG_INFO,"Find VTD (%d) [0x%08x] Exist\n", VTdIndex, DmarD=
rhd->RegisterBaseAddress));=0D
+ return;=0D
+ }=0D
+ }=0D
+=0D
+ for (VTdIndex =3D 0; VTdIndex < VTD_UNIT_MAX; VTdIndex++) {=0D
+ if (VtdUnitInfo[VTdIndex].VtdUnitBaseAddress =3D=3D 0) {=0D
+ VtdUnitInfo[VTdIndex].VtdUnitBaseAddress =3D (UINTN) DmarDrhd->Regis=
terBaseAddress;=0D
+ VtdUnitInfo[VTdIndex].Segment =3D DmarDrhd->SegmentNumber;=0D
+ VtdUnitInfo[VTdIndex].Flags =3D DmarDrhd->Flags;=0D
+ VtdUnitInfo[VTdIndex].Done =3D FALSE;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress - 0x%016lx\n", VTdIndex, D=
marDrhd->RegisterBaseAddress));=0D
+ DEBUG ((DEBUG_INFO," Segment - %d, Flags - 0x%x\n", DmarDrhd->Seg=
mentNumber, DmarDrhd->Flags));=0D
+ return;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VtdUnitInfo Table is full\n"));=0D
+ ASSERT (FALSE);=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Initializes the Intel VTd Info in post memory phase.=0D
+=0D
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized=
.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.=0D
+**/=0D
+EFI_STATUS=0D
+InitVTdInfo (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VTD_INFO *VTdInfo;=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+ UINTN VtdUnitNumber;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ VTdInfo =3D GetVTdInfoHob ();=0D
+ ASSERT (VTdInfo !=3D NULL);=0D
+=0D
+ AcpiDmarTable =3D GetAcpiDmarTable ();=0D
+ ASSERT (AcpiDmarTable !=3D NULL);=0D
+=0D
+ if (VTdInfo->VtdUnitInfo =3D=3D NULL) {=0D
+ //=0D
+ // Genrate a new Vtd Unit Info Table=0D
+ //=0D
+ VTdInfo->VtdUnitInfo =3D AllocateZeroPages (EFI_SIZE_TO_PAGES (sizeof =
(VTD_UNIT_INFO) * VTD_UNIT_MAX));=0D
+ if (VTdInfo->VtdUnitInfo =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "InitVTdInfo - OUT_OF_RESOURCE\n"));=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+ VtdUnitInfo =3D VTdInfo->VtdUnitInfo;=0D
+=0D
+ if (VTdInfo->HostAddressWidth =3D=3D 0) {=0D
+ VTdInfo->HostAddressWidth =3D AcpiDmarTable->HostAddressWidth;=0D
+ }=0D
+=0D
+ if (VTdInfo->HostAddressWidth !=3D AcpiDmarTable->HostAddressWidth) {=0D
+ DEBUG ((DEBUG_ERROR, "Host Address Width is not match.\n"));=0D
+ ASSERT (FALSE);=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ //=0D
+ // Parse the DMAR ACPI Table to the new Vtd Unit Info Table=0D
+ //=0D
+ VtdUnitNumber =3D ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDrhdPost=
Memory, VtdUnitInfo);=0D
+ if (VtdUnitNumber =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ for (VTdInfo->VTdEngineCount =3D 0; VTdInfo->VTdEngineCount < VTD_UNIT_M=
AX; VTdInfo->VTdEngineCount++) {=0D
+ if (VtdUnitInfo[VTdInfo->VTdEngineCount].VtdUnitBaseAddress =3D=3D 0) =
{=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ VTdInfo->AcpiDmarTable =3D AcpiDmarTable;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Initializes the Intel VTd DMAR for block all DMA.=0D
+=0D
+ @retval EFI_SUCCESS Driver is successfully initialized.=0D
+ @retval RETURN_NOT_READY Fail to get VTdInfo Hob .=0D
+**/=0D
+EFI_STATUS=0D
+InitVTdDmarBlockAll (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+=0D
+ //=0D
+ // Get the DMAR table=0D
+ //=0D
+ AcpiDmarTable =3D GetAcpiDmarTable ();=0D
+ ASSERT (AcpiDmarTable !=3D NULL);=0D
+=0D
+ //=0D
+ // Parse the DMAR table and block all DMA=0D
+ //=0D
+ return ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDhrdPreMemory, NULL=
);=0D
+}=0D
+=0D
+/**=0D
+ Initializes DMA buffer=0D
+=0D
+ @retval EFI_SUCCESS DMA buffer is successfully initialized.=0D
+ @retval EFI_INVALID_PARAMETER Invalid DMA buffer size.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize DMA buffer.=0D
+**/=0D
+EFI_STATUS=0D
+InitDmaBuffer(=0D
+ VOID=0D
+ )=0D
+{=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+ VOID *Hob;=0D
+ VOID *VtdPmrHobPtr;=0D
+ VTD_PMR_INFO_HOB *VtdPmrHob;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "InitDmaBuffer :\n"));=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ ASSERT(Hob !=3D NULL);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA (Hob);=0D
+=0D
+ /**=0D
+ When gVtdPmrInfoDataHobGuid exists, it means:=0D
+ 1. Dma buffer is reserved by memory initialize code=0D
+ 2. PeiGetVtdPmrAlignmentLib is used to get alignment=0D
+ 3. Protection regions are determined by the system memory map=0D
+ 4. Protection regions will be conveyed through VTD_PMR_INFO_HOB=0D
+=0D
+ When gVtdPmrInfoDataHobGuid dosen't exist, it means:=0D
+ 1. IntelVTdDmarPei driver will calcuate the protected memory alignment=
=0D
+ 2. Dma buffer is reserved by AllocateAlignedPages()=0D
+ **/=0D
+=0D
+=0D
+ if (DmaBufferInfo->DmaBufferSize =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferSize is 0\n"));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ if (DmaBufferInfo->DmaBufferBase =3D=3D 0) {=0D
+ VtdPmrHobPtr =3D GetFirstGuidHob (&gVtdPmrInfoDataHobGuid);=0D
+ if (VtdPmrHobPtr !=3D NULL) {=0D
+ //=0D
+ // Get the protected memory ranges information from the VTd PMR hob=
=0D
+ //=0D
+ VtdPmrHob =3D GET_GUID_HOB_DATA (VtdPmrHobPtr);=0D
+=0D
+ if ((VtdPmrHob->ProtectedHighBase - VtdPmrHob->ProtectedLowLimit) < =
DmaBufferInfo->DmaBufferSize) {=0D
+ DEBUG ((DEBUG_ERROR, " DmaBufferSize not enough\n"));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ DmaBufferInfo->DmaBufferBase =3D VtdPmrHob->ProtectedLowLimit;=0D
+ } else {=0D
+ //=0D
+ // Allocate memory for DMA buffer=0D
+ //=0D
+ DmaBufferInfo->DmaBufferBase =3D (UINTN) AllocateAlignedPages (EFI_S=
IZE_TO_PAGES (DmaBufferInfo->DmaBufferSize), 0);=0D
+ if (DmaBufferInfo->DmaBufferBase =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n"));=0D
+ }=0D
+=0D
+ DmaBufferInfo->DmaBufferCurrentTop =3D DmaBufferInfo->DmaBufferBase + =
DmaBufferInfo->DmaBufferSize;=0D
+ DmaBufferInfo->DmaBufferCurrentBottom =3D DmaBufferInfo->DmaBufferBase=
;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo-=
DmaBufferSize));=0D+ DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo-=
DmaBufferBase));=0D+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop : 0x%x\n", DmaBufferInfo->D=
maBufferCurrentTop));=0D
+ DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%x\n", DmaBufferInfo->D=
maBufferCurrentBottom));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_PROTECT_MEMORY_RANGE, DmaBufferInfo->DmaBuffe=
rCurrentBottom, DmaBufferInfo->DmaBufferCurrentTop);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Initializes the Intel VTd DMAR for DMA buffer.=0D
+=0D
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized=
.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+InitVTdDmarForDma (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VTD_INFO *VTdInfo;=0D
+=0D
+ EFI_STATUS Status;=0D
+ EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;=0D
+ EDKII_IOMMU_PPI *OldIoMmuPpi;=0D
+=0D
+ VTdInfo =3D GetVTdInfoHob ();=0D
+ ASSERT (VTdInfo !=3D NULL);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));=0D
+ Status =3D PrepareVtdConfig (VTdInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ return Status;=0D
+ }=0D
+=0D
+ // create root entry table=0D
+ DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));=0D
+ Status =3D SetupTranslationTable (VTdInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));=0D
+ Status =3D EnableVTdTranslationProtection(VTdInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Install gEdkiiIoMmuPpiGuid\n"));=0D
+ // install protocol=0D
+ //=0D
+ // (Re)Install PPI.=0D
+ //=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEdkiiIoMmuPpiGuid,=0D
+ 0,=0D
+ &OldDescriptor,=0D
+ (VOID **) &OldIoMmuPpi=0D
+ );=0D
+ if (!EFI_ERROR (Status)) {=0D
+ Status =3D PeiServicesReInstallPpi (OldDescriptor, &mIoMmuPpiList);=0D
+ } else {=0D
+ Status =3D PeiServicesInstallPpi (&mIoMmuPpiList);=0D
+ }=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ This function handles S3 resume task at the end of PEI=0D
+=0D
+ @param[in] PeiServices Pointer to PEI Services Table.=0D
+ @param[in] NotifyDesc Pointer to the descriptor for the Notifica=
tion event that=0D
+ caused this function to execute.=0D
+ @param[in] Ppi Pointer to the PPI data associated with th=
is function.=0D
+=0D
+ @retval EFI_STATUS Always return EFI_SUCCESS=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+S3EndOfPeiNotify(=0D
+ IN EFI_PEI_SERVICES **PeiServices,=0D
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,=0D
+ IN VOID *Ppi=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, "VTd DMAR PEI S3EndOfPeiNotify\n"));=0D
+=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) {=0D
+ DumpVtdIfError ();=0D
+=0D
+ DisableVTdTranslationProtection (GetVTdInfoHob ());=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc =3D {=0D
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA=
TE_LIST),=0D
+ &gEfiEndOfPeiSignalPpiGuid,=0D
+ S3EndOfPeiNotify=0D
+};=0D
+=0D
+/**=0D
+ This function handles VTd engine setup=0D
+=0D
+ @param[in] PeiServices Pointer to PEI Services Table.=0D
+ @param[in] NotifyDesc Pointer to the descriptor for the Notifica=
tion event that=0D
+ caused this function to execute.=0D
+ @param[in] Ppi Pointer to the PPI data associated with th=
is function.=0D
+=0D
+ @retval EFI_STATUS Always return EFI_SUCCESS=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+VTdInfoNotify (=0D
+ IN EFI_PEI_SERVICES **PeiServices,=0D
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,=0D
+ IN VOID *Ppi=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VOID *MemoryDiscovered;=0D
+ BOOLEAN MemoryInitialized;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));=0D
+=0D
+ //=0D
+ // Check if memory is initialized.=0D
+ //=0D
+ MemoryInitialized =3D FALSE;=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEfiPeiMemoryDiscoveredPpiGuid,=0D
+ 0,=0D
+ NULL,=0D
+ &MemoryDiscovered=0D
+ );=0D
+ if (!EFI_ERROR(Status)) {=0D
+ MemoryInitialized =3D TRUE;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));=0D
+=0D
+ if (!MemoryInitialized) {=0D
+ //=0D
+ // If the memory is not initialized,=0D
+ // Protect all system memory=0D
+ //=0D
+=0D
+ InitVTdDmarBlockAll ();=0D
+=0D
+ //=0D
+ // Install PPI.=0D
+ //=0D
+ Status =3D PeiServicesInstallPpi (&mIoMmuPpiList);=0D
+ ASSERT_EFI_ERROR(Status);=0D
+ } else {=0D
+ //=0D
+ // If the memory is initialized,=0D
+ // Allocate DMA buffer and protect rest system memory=0D
+ //=0D
+=0D
+ VTdLogInitialize (TRUE);=0D
+=0D
+ Status =3D InitDmaBuffer ();=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // NOTE: We need reinit VTdInfo because previous information might be =
overriden.=0D
+ //=0D
+ Status =3D InitVTdInfo ();=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D InitVTdDmarForDma ();=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc =3D {=0D
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA=
TE_LIST),=0D
+ &gEdkiiVTdInfoPpiGuid,=0D
+ VTdInfoNotify=0D
+};=0D
+=0D
+/**=0D
+ Initializes the Intel VTd DMAR PEIM.=0D
+=0D
+ @param[in] FileHandle Handle of the file being invoked.=0D
+ @param[in] PeiServices Describes the list of possible PEI Service=
s.=0D
+=0D
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized=
.=0D
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IntelVTdDmarInitialize (=0D
+ IN EFI_PEI_FILE_HANDLE FileHandle,=0D
+ IN CONST EFI_PEI_SERVICES **PeiServices=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_BOOT_MODE BootMode;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "IntelVTdDmarInitialize\n"));=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VTdLogInitialize (FALSE);=0D
+=0D
+ DmaBufferInfo =3D BuildGuidHob (&mDmaBufferInfoGuid, sizeof (DMA_BUFFER_=
INFO));=0D
+ ASSERT(DmaBufferInfo !=3D NULL);=0D
+ if (DmaBufferInfo =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ ZeroMem (DmaBufferInfo, sizeof (DMA_BUFFER_INFO));=0D
+=0D
+ PeiServicesGetBootMode (&BootMode);=0D
+=0D
+ if (BootMode =3D=3D BOOT_ON_S3_RESUME) {=0D
+ DmaBufferInfo->DmaBufferSize =3D PcdGet32 (PcdVTdPeiDmaBufferSizeS3);=
=0D
+ } else {=0D
+ DmaBufferInfo->DmaBufferSize =3D PcdGet32 (PcdVTdPeiDmaBufferSize);=0D
+ }=0D
+=0D
+ Status =3D PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Register EndOfPei Notify for S3=0D
+ //=0D
+ if (BootMode =3D=3D BOOT_ON_S3_RESUME) {=0D
+ Status =3D PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/I=
ntelVTdCorePei.h
new file mode 100644
index 000000000..1ddf8fbf7
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.h
@@ -0,0 +1,272 @@
+/** @file=0D
+ The definition for DMA access Library.=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef __DMA_ACCESS_LIB_H__=0D
+#define __DMA_ACCESS_LIB_H__=0D
+=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+//=0D
+// Use 256-bit descriptor=0D
+// Queue size is 128.=0D
+//=0D
+#define VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH 1=0D
+#define VTD_INVALIDATION_QUEUE_SIZE 0=0D
+=0D
+typedef struct {=0D
+ BOOLEAN Done;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Segment;=0D
+ UINT8 Flags;=0D
+ VTD_VER_REG VerReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ BOOLEAN Is5LevelPaging;=0D
+ UINT8 EnableQueuedInvalidation;=0D
+ VOID *QiDescBuffer;=0D
+ UINTN QiDescBufferSize;=0D
+ UINTN FixedSecondLevelPagingEntry;=0D
+ UINTN RootEntryTable;=0D
+ UINTN ExtRootEntryTable;=0D
+ UINTN RootEntryTablePageSize;=0D
+ UINTN ExtRootEntryTablePageSize;=0D
+} VTD_UNIT_INFO;=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;=0D
+ UINT8 HostAddressWidth;=0D
+ VTD_REGESTER_THIN_INFO *RegsInfoBuffer;=0D
+ UINTN VTdEngineCount;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+} VTD_INFO;=0D
+=0D
+typedef struct {=0D
+ UINTN DmaBufferBase;=0D
+ UINTN DmaBufferSize;=0D
+ UINTN DmaBufferCurrentTop;=0D
+ UINTN DmaBufferCurrentBottom;=0D
+} DMA_BUFFER_INFO;=0D
+=0D
+typedef=0D
+VOID=0D
+(*PROCESS_DRHD_CALLBACK_FUNC) (=0D
+ IN OUT VOID *Context,=0D
+ IN UINTN VTdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ );=0D
+=0D
+/**=0D
+ Enable VTd translation table protection for block DMA=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtectionBlockDma (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Enable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Disable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+**/=0D
+VOID=0D
+DisableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @param[in] AcpiDmarTable DMAR ACPI table=0D
+ @param[in] Callback Callback function for handle DRHD=0D
+ @param[in] Context Callback function Context=0D
+=0D
+ @return the VTd engine number.=0D
+=0D
+**/=0D
+UINTN=0D
+ParseDmarAcpiTableDrhd (=0D
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,=0D
+ IN PROCESS_DRHD_CALLBACK_FUNC Callback,=0D
+ IN VOID *Context=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+DumpAcpiDMAR (=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ );=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Prepare Vtd config success=0D
+**/=0D
+EFI_STATUS=0D
+PrepareVtdConfig (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ IN VTD_INFO *VTdInfo=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ );=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Get the VTd engine context information hob.=0D
+=0D
+ @retval The VTd engine context information.=0D
+=0D
+**/=0D
+VTD_INFO *=0D
+GetVTdInfoHob (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Add the VTd log event in post memory phase.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ );=0D
+=0D
+/**=0D
+ Add the VTd log event in pre-memory phase.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Mode Pre-memory DMA protection mode.=0D
+ @param[in] Status Status=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddPreMemoryEvent (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT8 Mode,=0D
+ IN UINT8 Status=0D
+ );=0D
+=0D
+extern EFI_GUID mVTdInfoGuid;=0D
+extern EFI_GUID mDmaBufferInfoGuid;=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei=
/IntelVTdCorePei.inf
new file mode 100644
index 000000000..f756c543c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.inf
@@ -0,0 +1,70 @@
+## @file=0D
+# Component INF file for the Intel VTd DMAR PEIM.=0D
+#=0D
+# This driver initializes VTd engine based upon EDKII_VTD_INFO_PPI=0D
+# and provide DMA protection in PEI.=0D
+#=0D
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010017=0D
+ BASE_NAME =3D IntelVTdCorePei=0D
+ MODULE_UNI_FILE =3D IntelVTdCorePei.uni=0D
+ FILE_GUID =3D 9311b0cc-5c08-4c0a-bec8-23afab024e48=0D
+ MODULE_TYPE =3D PEIM=0D
+ VERSION_STRING =3D 2.0=0D
+ ENTRY_POINT =3D IntelVTdDmarInitialize=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[Sources]=0D
+ IntelVTdCorePei.c=0D
+ IntelVTdCorePei.h=0D
+ IntelVTdDmar.c=0D
+ DmarTable.c=0D
+ TranslationTable.c=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ BaseMemoryLib=0D
+ BaseLib=0D
+ PeimEntryPoint=0D
+ PeiServicesLib=0D
+ HobLib=0D
+ IoLib=0D
+ CacheMaintenanceLib=0D
+ PciSegmentLib=0D
+ IntelVTdPeiDxeLib=0D
+=0D
+[Guids]=0D
+ gVTdLogBufferHobGuid ## PRODUCES CONSUMES=0D
+ gVtdPmrInfoDataHobGuid ## CONSUMES=0D
+=0D
+[Ppis]=0D
+ gEdkiiIoMmuPpiGuid ## PRODUCES=0D
+ gEdkiiVTdInfoPpiGuid ## CONSUMES=0D
+ gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES=0D
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES=0D
+ gEdkiiVTdNullRootEntryTableGuid ## CONSUMES=0D
+=0D
+[Pcd]=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSize ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3 ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize ## CONSUME=
S=0D
+=0D
+[Depex]=0D
+ gEfiPeiMasterBootModePpiGuid AND=0D
+ gEdkiiVTdInfoPpiGuid=0D
+=0D
+[UserExtensions.TianoCore."ExtraFiles"]=0D
+ IntelVTdCorePeiExtra.uni=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePei.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei=
/IntelVTdCorePei.uni
new file mode 100644
index 000000000..2b5b260f5
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePei.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDmarPei Module Localized Abstract and Description Content=0D
+//=0D
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Intel VTd CORE PE=
I Driver."=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "This driver initi=
alizes VTd engine based upon EDKII_VTD_INFO_PPI and provide DMA protection =
to device in PEI."=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdCorePeiExtra.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCo=
rePei/IntelVTdCorePeiExtra.uni
new file mode 100644
index 000000000..14848f924
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdCor=
ePeiExtra.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDmarPei Localized Strings and Content=0D
+//=0D
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+#string STR_PROPERTIES_MODULE_NAME=0D
+#language en-US=0D
+"Intel VTd CORE PEI Driver"=0D
+=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Inte=
lVTdDmar.c
new file mode 100644
index 000000000..d3876416c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/IntelVTdDma=
r.c
@@ -0,0 +1,727 @@
+/** @file=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/PeiServicesLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Ppi/VtdNullRootEntryTable.h>=0D
+#include <Ppi/IoMmu.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+#define VTD_CAP_REG_NFR_MAX (256)=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ if (VtdUnitInfo->ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *) Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_IQA_REG IqaReg;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ if (VtdUnitInfo->VerReg.Bits.Major <=3D 5) {=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for eng=
ine [0x%x]\n", VtdUnitBaseAddress));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);=0D
+ if (ECapReg.Bits.QI =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations i=
nterface for engine [0x%x]\n", VtdUnitBaseAddress));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 1;=0D
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]=
\n", VtdUnitBaseAddress));=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ if ((Reg32 & B_GSTS_REG_QIES) !=3D 0) {=0D
+ DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n"));=0D
+=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitBaseAddress);=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the Invalidation Queue Tail Register to zero.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);=0D
+=0D
+ //=0D
+ // Setup the IQ address, size and descriptor width through the Invalidat=
ion Queue Address Register=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ VtdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <=
< (VTD_INVALIDATION_QUEUE_SIZE + 7)));=0D
+ VtdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VtdUni=
tInfo->QiDescBufferSize));=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"))=
;=0D
+ VTdLogAddEvent (VTDLOG_PEI_QUEUED_INVALIDATION, VTD_LOG_QI_ERROR_OUT=
_OF_RESOURCES, VtdUnitBaseAddress);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VtdUnitInfo=
->QiDescBufferSize));=0D
+ //=0D
+ // 4KB Aligned address=0D
+ //=0D
+ IqaReg.Uint64 =3D (UINT64) (UINTN) VtdUnitInfo->QiDescBuffer;=0D
+ IqaReg.Bits.DW =3D VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH;=0D
+ IqaReg.Bits.QS =3D VTD_INVALIDATION_QUEUE_SIZE;=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ DEBUG ((DEBUG_INFO, "IQA_REG =3D 0x%lx, IQH_REG =3D 0x%lx\n", IqaReg.Uin=
t64, MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));=0D
+=0D
+ //=0D
+ // Enable the queued invalidation interface through the Global Command R=
egister.=0D
+ // When enabled, hardware sets the QIES field in the Global Status Regis=
ter.=0D
+ //=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 |=3D B_GMCD_REG_QIE;=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG =3D =
0x%x\n", Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_QUEUED_INVALIDATION, VTD_LOG_QI_ENABLE, VtdUn=
itBaseAddress);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+SubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN QI_256_DESC *Desc=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_REGESTER_QI_INFO RegisterQi;=0D
+=0D
+ Status =3D VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress,=
Desc, FALSE);=0D
+ if (Status =3D=3D EFI_DEVICE_ERROR) {=0D
+ RegisterQi.BaseAddress =3D VtdUnitBaseAddress;=0D
+ RegisterQi.FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG=
);;=0D
+ RegisterQi.IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_R=
EG);=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_QI, &Register=
Qi, sizeof (VTD_REGESTER_QI_INFO));=0D
+=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, RegisterQi.FstsReg & (B_=
FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE));=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);=0D
+ if ((Reg64 & B_CCMD_REG_ICC) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC i=
s set for VTD(%x)\n", VtdUnitInfo->VtdUnitBaseAddress));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));=0D
+ Reg64 |=3D (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);=0D
+ MmioWrite64 (VtdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);=
=0D
+ } while ((Reg64 & B_CCMD_REG_ICC) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC=
_GRAN(1) | QI_CC_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(VtdUnitInfo->VtdUnitBaseAddr=
ess, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_ECA=
P_REG);=0D
+=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.=
IRO * 16) + R_IOTLB_REG);=0D
+ if ((Reg64 & B_IOTLB_REG_IVT) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is se=
t for VTD(%x)\n", VtdUnitInfo->VtdUnitBaseAddress));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));=0D
+ Reg64 |=3D (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);=0D
+ MmioWrite64 (VtdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16)=
+ R_IOTLB_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bit=
s.IRO * 16) + R_IOTLB_REG);=0D
+ } while ((Reg64 & B_IOTLB_REG_IVT) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitInfo->VtdUnitBaseAddress + R_CAP_=
REG);=0D
+ QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(CapR=
eg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(CapReg.Uint64)) | QI_IOTLB_GRAN(1=
) | QI_IOTLB_TYPE;=0D
+ QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0=
);=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(VtdUnitInfo->VtdUnitBaseAddr=
ess, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation in pre-mem phase.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] RtaddrRegValue The value of RTADDR_REG.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmarPreMem (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT64 RtaddrRegValue=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+=0D
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUn=
itBaseAddress));=0D
+=0D
+ DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue));=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, RtaddrRegValue);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmarPreMem: waiting for RTPS bit to be set...=
\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP)=
;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG =3D 0x%x \n", Reg32));=
=0D
+=0D
+ //=0D
+ // Write Buffer Flush=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);=
=0D
+=0D
+ DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] RootEntryTable The address of the VTd RootEntryTable.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN UINTN RootEntryTable=0D
+ )=0D
+{=0D
+ UINTN VtdUnitBaseAddress;=0D
+ BOOLEAN TEWasEnabled;=0D
+=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBase=
Address));=0D
+=0D
+ //=0D
+ // Check TE was enabled or not.=0D
+ //=0D
+ TEWasEnabled =3D ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GSTS=
_REG_TE) =3D=3D B_GSTS_REG_TE);=0D
+=0D
+ if (TEWasEnabled && (VtdUnitInfo->ECapReg.Bits.ADMS =3D=3D 1) && PcdGetB=
ool (PcdVTdSupportAbortDmaMode)) {=0D
+ //=0D
+ // For implementations reporting Enhanced SRTP Support (ESRTPS) field =
as=0D
+ // Clear in the Capability register, software must not modify this fie=
ld while=0D
+ // DMA remapping is active (TES=3D1 in Global Status register).=0D
+ //=0D
+ if (VtdUnitInfo->CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG=
_TE);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable ADM=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (RootEntryTab=
le | V_RTADDR_REG_TTM_ADM));=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"=
));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRT=
P);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Enable Abort DMA Mode...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ } else {=0D
+ DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTabl=
e);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"=
));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRT=
P);=0D
+ }=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ InvalidateContextCache (VtdUnitInfo);=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ InvalidateIOTLB (VtdUnitInfo);=0D
+=0D
+ if (TEWasEnabled && (VtdUnitInfo->ECapReg.Bits.ADMS =3D=3D 1) && PcdGetB=
ool (PcdVTdSupportAbortDmaMode)) {=0D
+ if (VtdUnitInfo->CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG=
_TE);=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTabl=
e);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"=
));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRT=
P);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);=
=0D
+=0D
+ DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Enable VTd translation table protection for block DMA=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtectionBlockDma (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI *RootEntryTable;=0D
+ UINT8 Mode;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n",=
VtdUnitBaseAddress));=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", PcdGetBool (PcdV=
TdSupportAbortDmaMode)));=0D
+=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);=0D
+ DEBUG ((DEBUG_INFO, "ECapReg.ADMS : %d\n", ECapReg.Bits.ADMS));=0D
+=0D
+ if ((ECapReg.Bits.ADMS =3D=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMod=
e)) {=0D
+ Mode =3D VTD_LOG_PEI_PRE_MEM_ADM;=0D
+ //=0D
+ // Use Abort DMA Mode=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "Enable abort DMA mode.\n"));=0D
+ Status =3D EnableDmarPreMem (VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM)=
;=0D
+ } else {=0D
+ //=0D
+ // Use Null Root Entry Table=0D
+ //=0D
+ Status =3D PeiServicesLocatePpi (=0D
+ &gEdkiiVTdNullRootEntryTableGuid,=0D
+ 0,=0D
+ NULL,=0D
+ (VOID **)&RootEntryTable=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ Mode =3D VTD_LOG_PEI_PRE_MEM_DISABLE;=0D
+ DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n=
", Status));=0D
+ ASSERT (FALSE);=0D
+ } else {=0D
+ Mode =3D VTD_LOG_PEI_PRE_MEM_TE;=0D
+ DEBUG ((DEBUG_INFO, "Block All DMA by TE.\n"));=0D
+ Status =3D EnableDmarPreMem (VtdUnitBaseAddress, (UINT64) (*RootEntr=
yTable));=0D
+ }=0D
+ }=0D
+=0D
+ VTdLogAddPreMemoryEvent (VtdUnitBaseAddress, Mode, EFI_ERROR (Status) ? =
0 : 1);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Enable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+ if (VtdUnitInfo->Done) {=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index));=0D
+ continue;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ExtRootEntryTable !=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", I=
ndex, VtdUnitInfo->ExtRootEntryTable));=0D
+ Status =3D EnableDmar (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable |=
BIT11);=0D
+ } else {=0D
+ DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", Inde=
x, VtdUnitInfo->RootEntryTable));=0D
+ Status =3D EnableDmar (VtdUnitInfo, VtdUnitInfo->RootEntryTable);=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_PEI_POST_MEM_ENABLE_DMA_PROTECT, VTdInfo->VtdUn=
itInfo[Index].VtdUnitBaseAddress, Status);=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", Index));=0D
+ return Status;=0D
+ }=0D
+ VtdUnitInfo->Done =3D TRUE;=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable VTd translation table protection.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+**/=0D
+VOID=0D
+DisableVTdTranslationProtection (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ if (VTdInfo =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - %d Vtd Engine\n",=
VTdInfo->VTdEngineCount));=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+=0D
+ VtdLibDisableDmar (VtdUnitInfo->VtdUnitBaseAddress);=0D
+ VTdLogAddEvent (VTDLOG_PEI_POST_MEM_DISABLE_DMA_PROTECT, VtdUnitInfo->=
VtdUnitBaseAddress, 0);=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation !=3D 0) {=0D
+ //=0D
+ // Disable queued invalidation interface.=0D
+ //=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitInfo->VtdUnitBaseAd=
dress);=0D
+=0D
+ if (VtdUnitInfo->QiDescBuffer !=3D NULL) {=0D
+ FreePages(VtdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VtdUnitInf=
o->QiDescBufferSize));=0D
+ VtdUnitInfo->QiDescBuffer =3D NULL;=0D
+ VtdUnitInfo->QiDescBufferSize =3D 0;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ VTdLogAddEvent (VTDLOG_PEI_QUEUED_INVALIDATION, VTD_LOG_QI_DISABLE, =
VtdUnitInfo->VtdUnitBaseAddress);=0D
+ }=0D
+ }=0D
+=0D
+ return;=0D
+}=0D
+=0D
+/**=0D
+ Check if VTd engine use 5 level paging.=0D
+=0D
+ @param[in] HostAddressWidth Host Address Width.=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[out] Is5LevelPaging Use 5 level paging or not=0D
+=0D
+ @retval EFI_SUCCESS Success=0D
+ @retval EFI_UNSUPPORTED Feature is not support=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VtdCheckUsing5LevelPaging (=0D
+ IN UINT8 HostAddressWidth,=0D
+ IN VTD_CAP_REG CapReg,=0D
+ OUT BOOLEAN *Is5LevelPaging=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, " CapReg SAGAW bits : 0x%02x\n", CapReg.Bits.SAGAW)=
);=0D
+=0D
+ *Is5LevelPaging =3D FALSE;=0D
+ if ((CapReg.Bits.SAGAW & BIT3) !=3D 0) {=0D
+ *Is5LevelPaging =3D TRUE;=0D
+ if ((HostAddressWidth <=3D 48) &&=0D
+ ((CapReg.Bits.SAGAW & BIT2) !=3D 0)) {=0D
+ *Is5LevelPaging =3D FALSE;=0D
+ } else {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ }=0D
+ if ((CapReg.Bits.SAGAW & (BIT3 | BIT2)) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, " Using %d Level Paging\n", *Is5LevelPaging ? 5 : 4=
));=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Prepare Vtd config success=0D
+**/=0D
+EFI_STATUS=0D
+PrepareVtdConfig (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ if (VTdInfo->RegsInfoBuffer =3D=3D NULL) {=0D
+ VTdInfo->RegsInfoBuffer =3D AllocateZeroPages (EFI_SIZE_TO_PAGES (size=
of (VTD_REGESTER_THIN_INFO) + sizeof (VTD_UINT128) * VTD_CAP_REG_NFR_MAX));=
=0D
+ ASSERT (VTdInfo->RegsInfoBuffer !=3D NULL);=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+ if (VtdUnitInfo->Done) {=0D
+ continue;=0D
+ }=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+ DEBUG ((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitBaseAddress));=0D
+=0D
+ VtdUnitInfo->VerReg.Uint32 =3D MmioRead32 (VtdUnitBaseAddress + R_VER_=
REG);=0D
+ VtdUnitInfo->CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_=
REG);=0D
+ VtdUnitInfo->ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECA=
P_REG);=0D
+ DEBUG ((DEBUG_INFO, " VER_REG : 0x%08X\n", VtdUnitInfo->VerReg.Uint3=
2));=0D
+ DEBUG ((DEBUG_INFO, " CAP_REG : 0x%016lX\n", VtdUnitInfo->CapReg.Uin=
t64));=0D
+ DEBUG ((DEBUG_INFO, " ECAP_REG : 0x%016lX\n", VtdUnitInfo->ECapReg.Ui=
nt64));=0D
+=0D
+ Status =3D VtdCheckUsing5LevelPaging (VTdInfo->HostAddressWidth, VtdUn=
itInfo->CapReg, &(VtdUnitInfo->Is5LevelPaging));=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported!!!!=
\n", VtdUnitInfo->CapReg.Bits.SAGAW));=0D
+ return Status;=0D
+ }=0D
+=0D
+ Status =3D PerpareCacheInvalidationInterface(&VTdInfo->VtdUnitInfo[Ind=
ex]);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VTD_INFO *VTdInfo;=0D
+ UINTN Num;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Index;=0D
+ VTD_REGESTER_THIN_INFO *VtdRegInfo;=0D
+ VTD_FRCD_REG FrcdReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ UINT32 FstsReg32;=0D
+ UINT32 FectlReg32;=0D
+ BOOLEAN HasError;=0D
+=0D
+ VTdInfo =3D GetVTdInfoHob ();=0D
+ if (VTdInfo =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VtdRegInfo =3D VTdInfo->RegsInfoBuffer;=0D
+ if (VtdRegInfo =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ for (Num =3D 0; Num < VTdInfo->VTdEngineCount; Num++) {=0D
+ HasError =3D FALSE;=0D
+ VtdUnitBaseAddress =3D VTdInfo->VtdUnitInfo[Num].VtdUnitBaseAddress;=0D
+ FstsReg32 =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG);=0D
+ if (FstsReg32 !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+ FectlReg32 =3D MmioRead32 (VtdUnitBaseAddress + R_FECTL_REG);=0D
+ if ((FectlReg32 & BIT30) !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ }=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+ for (Index =3D 0; Index < (UINT16) CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[0] =3D MmioRead64 (VtdUnitBaseAddress + ((CapReg.Bits=
.FRO * 16) + (Index * 16) + R_FRCD_REG));=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (VtdUnitBaseAddress + ((CapReg.Bits=
.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ HasError =3D TRUE;=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ if (HasError) {=0D
+ DEBUG ((DEBUG_INFO, "\n#### ERROR ####\n"));=0D
+=0D
+ VtdRegInfo->BaseAddress =3D VtdUnitBaseAddress;=0D
+ VtdRegInfo->GstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_=
REG);=0D
+ VtdRegInfo->RtaddrReg =3D MmioRead64 (VtdUnitBaseAddress + R_RTADD=
R_REG);;=0D
+ VtdRegInfo->FstsReg =3D FstsReg32;=0D
+ VtdRegInfo->FectlReg =3D FectlReg32;=0D
+ VtdRegInfo->IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERC=
D_REG);=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+ for (Index =3D 0; Index < (UINT16) CapReg.Bits.NFR + 1; Index++) {=0D
+ VtdRegInfo->FrcdReg[Index].Uint64Lo =3D MmioRead64 (VtdUnitBaseAdd=
ress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));=0D
+ VtdRegInfo->FrcdReg[Index].Uint64Hi =3D MmioRead64 (VtdUnitBaseAdd=
ress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)=
));=0D
+ }=0D
+ VtdRegInfo->FrcdRegNum =3D Index;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "\n#### ERROR ####\n"));=0D
+=0D
+ VtdLibDumpVtdRegsThin (NULL, NULL, VtdRegInfo);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "#### ERROR ####\n\n"));=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_THIN, VtdRe=
gInfo, sizeof (VTD_REGESTER_THIN_INFO) + sizeof (VTD_UINT128) * (VtdRegInfo=
->FrcdRegNum - 1));=0D
+=0D
+ //=0D
+ // Clear=0D
+ //=0D
+ for (Index =3D 0; Index < (UINT16) CapReg.Bits.NFR + 1; Index++) {=0D
+ FrcdReg.Uint64[1] =3D MmioRead64 (VtdUnitBaseAddress + ((CapReg.Bi=
ts.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));=0D
+ if (FrcdReg.Bits.F !=3D 0) {=0D
+ //=0D
+ // Software writes the value read from this field (F) to Clear i=
t.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Ind=
ex * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.Uint64[1]);=0D
+ }=0D
+ }=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, MmioRead32 (VtdUnitBas=
eAddress + R_FSTS_REG));=0D
+ }=0D
+ }=0D
+}
\ No newline at end of file
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Tran=
slationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/=
TranslationTable.c
new file mode 100644
index 000000000..03a4544a0
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCorePei/Translation=
Table.c
@@ -0,0 +1,926 @@
+/** @file=0D
+=0D
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiPei.h>=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/PeiServicesLib.h>=0D
+#include <Library/HobLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+#include <Ppi/IoMmu.h>=0D
+#include <Ppi/VtdInfo.h>=0D
+#include <Ppi/MemoryDiscovered.h>=0D
+#include <Ppi/EndOfPeiPhase.h>=0D
+#include <Guid/VtdPmrInfoHob.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Guid/VtdLogDataHob.h>=0D
+#include "IntelVTdCorePei.h"=0D
+=0D
+#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (=
~((Alignment) - 1)))=0D
+#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))=
=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ )=0D
+{=0D
+ VOID *Addr;=0D
+=0D
+ Addr =3D AllocatePages (Pages);=0D
+ if (Addr =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ ZeroMem (Addr, EFI_PAGES_TO_SIZE (Pages));=0D
+ return Addr;=0D
+}=0D
+=0D
+/**=0D
+ Set second level paging entry attribute based upon IoMmuAccess.=0D
+=0D
+ @param[in] PtEntry The paging entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+**/=0D
+VOID=0D
+SetSecondLevelPagingEntryAttribute (=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PtEntry,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ PtEntry->Bits.Read =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_READ) !=3D 0)=
;=0D
+ PtEntry->Bits.Write =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_WRITE) !=3D 0=
);=0D
+ DEBUG ((DEBUG_VERBOSE, "SetSecondLevelPagingEntryAttribute - 0x%x - 0x%x=
\n", PtEntry, IoMmuAccess));=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry table.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] MemoryBase The base of the memory.=0D
+ @param[in] MemoryLimit The limit of the memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntryTable (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 MemoryBase,=0D
+ IN UINT64 MemoryLimit,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Lvl5Start;=0D
+ UINTN Lvl5End;=0D
+ UINTN Lvl4PagesStart;=0D
+ UINTN Lvl4PagesEnd;=0D
+ UINTN Lvl4Start;=0D
+ UINTN Lvl4End;=0D
+ UINTN Lvl3Start;=0D
+ UINTN Lvl3End;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 EndAddress;=0D
+ BOOLEAN Is5LevelPaging;=0D
+=0D
+ if (MemoryLimit =3D=3D 0) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ Lvl4PagesStart =3D 0;=0D
+ Lvl4PagesEnd =3D 0;=0D
+ Lvl4PtEntry =3D NULL;=0D
+ Lvl5PtEntry =3D NULL;=0D
+=0D
+ BaseAddress =3D ALIGN_VALUE_LOW (MemoryBase, SIZE_2MB);=0D
+ EndAddress =3D ALIGN_VALUE_UP (MemoryLimit, SIZE_2MB);=0D
+ DEBUG ((DEBUG_INFO, "CreateSecondLevelPagingEntryTable: BaseAddress - 0x=
%016lx, EndAddress - 0x%016lx\n", BaseAddress, EndAddress));=0D
+=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ SecondLevelPagingEntry =3D AllocateZeroPages (1);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "Could not Alloc LVL4 or LVL5 PT. \n"));=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) SecondLevelPagingEntry, EFI=
_PAGES_TO_SIZE (1));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINT=
N) SecondLevelPagingEntry));=0D
+ //=0D
+ // If no access is needed, just create not present entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx Access 0\n", (UI=
NT64) (UINTN) SecondLevelPagingEntry));=0D
+ return SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ Is5LevelPaging =3D VtdUnitInfo->Is5LevelPaging;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D RShiftU64 (EndAddress - 1, 48) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO, " Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start,=
Lvl5End));=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+=0D
+ Lvl4PagesStart =3D (Lvl5Start<<9) | Lvl4Start;=0D
+ Lvl4PagesEnd =3D (Lvl5End<<9) | Lvl4End;=0D
+ DEBUG ((DEBUG_INFO, " Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", =
Lvl4PagesStart, Lvl4PagesEnd));=0D
+=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) SecondLevelPagingEnt=
ry;=0D
+ } else {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D Lvl5Start;=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO, " Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start,=
Lvl4End));=0D
+=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) SecondLevelPagingEnt=
ry;=0D
+ }=0D
+=0D
+ for (Index5 =3D Lvl5Start; Index5 <=3D Lvl5End; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ Lvl5PtEntry[Index5].Uint64 =3D (UINT64) (UINTN) AllocateZeroPages =
(1);=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!=
!\n", Index5));=0D
+ ASSERT (FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl5PtEntry[Index5].Uin=
t64, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+ Lvl4Start =3D Lvl4PagesStart & 0x1FF;=0D
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {=0D
+ Lvl4End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;=0D
+ Lvl4PagesStart =3D (Index5+1)<<9;=0D
+ } else {=0D
+ Lvl4End =3D Lvl4PagesEnd & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, " Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\=
n", Index5, Lvl4Start, Lvl4End));=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTD_64BITS=
_ADDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Addre=
ssHi);=0D
+ }=0D
+=0D
+ for (Index4 =3D Lvl4Start; Index4 <=3D Lvl4End; Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ Lvl4PtEntry[Index4].Uint64 =3D (UINT64) (UINTN) AllocateZeroPages =
(1);=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!=
!\n", Index4));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl4PtEntry[Index4].Uin=
t64, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl3Start =3D RShiftU64 (BaseAddress, 30) & 0x1FF;=0D
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=3D EndAddres=
s) {=0D
+ Lvl3End =3D SIZE_4KB / sizeof (VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;=
=0D
+ } else {=0D
+ Lvl3End =3D RShiftU64 (EndAddress - 1, 30) & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, " Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\=
n", Index4, Lvl3Start, Lvl3End));=0D
+=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTD_64BITS=
_ADDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Addre=
ssHi);=0D
+ for (Index3 =3D Lvl3Start; Index3 <=3D Lvl3End; Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ Lvl3PtEntry[Index3].Uint64 =3D (UINT64) (UINTN) AllocateZeroPage=
s (1);=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x=
%x)!!!!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl3PtEntry[Index3].U=
int64, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_=
IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTD_64BI=
TS_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Add=
ressHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ Lvl2PtEntry[Index2].Uint64 =3D BaseAddress;=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuA=
ccess);=0D
+ Lvl2PtEntry[Index2].Bits.PageSize =3D 1;=0D
+ BaseAddress +=3D SIZE_2MB;=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) Lvl2PtEntry, SIZE_4KB);=
=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &Lvl3PtEntry[Lvl3Start], =
(UINTN) &Lvl3PtEntry[Lvl3End + 1] - (UINTN) &Lvl3PtEntry[Lvl3Start]);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &Lvl4PtEntry[Lvl4Start], (U=
INTN) &Lvl4PtEntry[Lvl4End + 1] - (UINTN) &Lvl4PtEntry[Lvl4Start]);=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &Lvl5PtEntry[Lvl5Start], (UIN=
TN) &Lvl5PtEntry[Lvl5End + 1] - (UINTN) &Lvl5PtEntry[Lvl5Start]);=0D
+=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINT=
N) SecondLevelPagingEntry));=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Create context entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS The context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create context entry=
.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+CreateContextEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ UINTN EntryTablePages;=0D
+ VOID *Buffer;=0D
+ UINTN RootIndex;=0D
+ UINTN ContextIndex;=0D
+ VTD_ROOT_ENTRY *RootEntryBase;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ if (VtdUnitInfo->RootEntryTable !=3D 0) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTR=
Y_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CON=
TEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER);=
=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_ERROR, "RootEntryTable address - 0x%x\n", Buffer));=0D
+ VtdUnitInfo->RootEntryTable =3D (UINTN) Buffer;=0D
+ VtdUnitInfo->RootEntryTablePageSize =3D EntryTablePages;=0D
+ RootEntryBase =3D (VTD_ROOT_ENTRY *) Buffer;=0D
+ Buffer =3D (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));=0D
+ ASSERT(FALSE);=0D
+ }=0D
+=0D
+ for (RootIndex =3D 0; RootIndex < VTD_ROOT_ENTRY_NUMBER; RootIndex++) {=
=0D
+ SourceId.Index.RootIndex =3D (UINT8) RootIndex;=0D
+=0D
+ RootEntry =3D &RootEntryBase[SourceId.Index.RootIndex];=0D
+ RootEntry->Bits.ContextTablePointerLo =3D (UINT32) RShiftU64 ((UINT64=
) (UINTN) Buffer, 12);=0D
+ RootEntry->Bits.ContextTablePointerHi =3D (UINT32) RShiftU64 ((UINT64=
) (UINTN) Buffer, 32);=0D
+ RootEntry->Bits.Present =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS=
(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointer=
Hi);=0D
+=0D
+ for (ContextIndex =3D 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; Cont=
extIndex++) {=0D
+ SourceId.Index.ContextIndex =3D (UINT8) ContextIndex;=0D
+ ContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex];=0D
+=0D
+ ContextEntry->Bits.TranslationType =3D 0;=0D
+ ContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ContextEntry->Bits.Present =3D 0;=0D
+=0D
+ ContextEntry->Bits.AddressWidth =3D VtdUnitInfo->Is5LevelPaging ? 0x=
3 : 0x2;=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry !=3D 0) {=0D
+ SecondLevelPagingEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) VtdUn=
itInfo->FixedSecondLevelPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry,=
12);=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32=
) Pt;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32=
) RShiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)VtdU=
nitInfo->CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdUnitInfo, VtdUnitInfo->RootEntryTable, EFI_PAGE=
S_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended cont=
ext entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ UINTN EntryTablePages;=0D
+ VOID *Buffer;=0D
+ UINTN RootIndex;=0D
+ UINTN ContextIndex;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntryBase;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ if (VtdUnitInfo->ExtRootEntryTable !=3D 0) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_=
ENTRY_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD=
_CONTEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER);=
=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO, "Could not Alloc Root Entry Table !\n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_ERROR, "ExtRootEntryTable address - 0x%x\n", Buffer));=0D
+ VtdUnitInfo->ExtRootEntryTable =3D (UINTN) Buffer;=0D
+ VtdUnitInfo->ExtRootEntryTablePageSize =3D EntryTablePages;=0D
+ ExtRootEntryBase =3D (VTD_EXT_ROOT_ENTRY *) Buffer;=0D
+ Buffer =3D (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));=0D
+ ASSERT(FALSE);=0D
+ }=0D
+=0D
+ for (RootIndex =3D 0; RootIndex < VTD_ROOT_ENTRY_NUMBER; RootIndex++) {=
=0D
+ SourceId.Index.RootIndex =3D (UINT8)RootIndex;=0D
+=0D
+ ExtRootEntry =3D &ExtRootEntryBase[SourceId.Index.RootIndex];=0D
+ ExtRootEntry->Bits.LowerContextTablePointerLo =3D (UINT32) RShiftU64 =
((UINT64) (UINTN) Buffer, 12);=0D
+ ExtRootEntry->Bits.LowerContextTablePointerHi =3D (UINT32) RShiftU64 =
((UINT64) (UINTN) Buffer, 32);=0D
+ ExtRootEntry->Bits.LowerPresent =3D 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerLo =3D (UINT32) RShiftU64 =
((UINT64) (UINTN) Buffer, 12) + 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerHi =3D (UINT32) RShiftU64 =
(RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);=0D
+ ExtRootEntry->Bits.UpperPresent =3D 1;=0D
+ Buffer =3D (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_=
ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.=
LowerContextTablePointerHi);=0D
+=0D
+ for (ContextIndex =3D 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; Cont=
extIndex++) {=0D
+ SourceId.Index.ContextIndex =3D (UINT8) ContextIndex;=0D
+ ExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.ContextInde=
x];=0D
+=0D
+ ExtContextEntry->Bits.TranslationType =3D 0;=0D
+ ExtContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ExtContextEntry->Bits.Present =3D 0;=0D
+=0D
+ ExtContextEntry->Bits.AddressWidth =3D VtdUnitInfo->Is5LevelPaging ?=
0x3 : 0x2;=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry !=3D 0) {=0D
+ SecondLevelPagingEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *) VtdUn=
itInfo->FixedSecondLevelPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry,=
12);=0D
+=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UIN=
T32) Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UIN=
T32) RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8) ((UINTN)=
VtdUnitInfo->CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable, EFI_P=
AGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+#define VTD_PG_R BIT0=0D
+#define VTD_PG_W BIT1=0D
+#define VTD_PG_X BIT2=0D
+#define VTD_PG_EMT (BIT3 | BIT4 | BIT5)=0D
+#define VTD_PG_TM (BIT62)=0D
+=0D
+#define VTD_PG_PS BIT7=0D
+=0D
+#define PAGE_PROGATE_BITS (VTD_PG_TM | VTD_PG_EMT | VTD_PG_W | VT=
D_PG_R)=0D
+=0D
+#define PAGING_4K_MASK 0xFFF=0D
+#define PAGING_2M_MASK 0x1FFFFF=0D
+#define PAGING_1G_MASK 0x3FFFFFFF=0D
+=0D
+#define PAGING_VTD_INDEX_MASK 0x1FF=0D
+=0D
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull=0D
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull=0D
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull=0D
+=0D
+typedef enum {=0D
+ PageNone,=0D
+ Page4K,=0D
+ Page2M,=0D
+ Page1G,=0D
+} PAGE_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ PAGE_ATTRIBUTE Attribute;=0D
+ UINT64 Length;=0D
+ UINT64 AddressMask;=0D
+} PAGE_ATTRIBUTE_TABLE;=0D
+=0D
+PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D {=0D
+ {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},=0D
+ {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},=0D
+ {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},=0D
+};=0D
+=0D
+/**=0D
+ Return length according to page attributes.=0D
+=0D
+ @param[in] PageAttributes The page attribute of the page entry.=0D
+=0D
+ @return The length of page entry.=0D
+**/=0D
+UINTN=0D
+PageAttributeToLength (=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ for (Index =3D 0; Index < sizeof (mPageAttributeTable) / sizeof (mPageAt=
tributeTable[0]); Index++) {=0D
+ if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) {=0D
+ return (UINTN) mPageAttributeTable[Index].Length;=0D
+ }=0D
+ }=0D
+ return 0;=0D
+}=0D
+=0D
+/**=0D
+ Return page table entry to match the address.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in V=
Td table for the device.=0D
+ @param[in] Address The address to be checked.=0D
+ @param[out] PageAttributes The page attribute of the page ent=
ry.=0D
+=0D
+ @return The page entry.=0D
+**/=0D
+VOID *=0D
+GetSecondLevelPageTableEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN PHYSICAL_ADDRESS Address,=0D
+ OUT PAGE_ATTRIBUTE *PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index1;=0D
+ UINTN Index2;=0D
+ UINTN Index3;=0D
+ UINTN Index4;=0D
+ UINTN Index5;=0D
+ UINT64 *L1PageTable;=0D
+ UINT64 *L2PageTable;=0D
+ UINT64 *L3PageTable;=0D
+ UINT64 *L4PageTable;=0D
+ UINT64 *L5PageTable;=0D
+ BOOLEAN Is5LevelPaging;=0D
+=0D
+ Index5 =3D ((UINTN) RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;=0D
+ Index4 =3D ((UINTN) RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;=0D
+ Index3 =3D ((UINTN) Address >> 30) & PAGING_VTD_INDEX_MASK;=0D
+ Index2 =3D ((UINTN) Address >> 21) & PAGING_VTD_INDEX_MASK;=0D
+ Index1 =3D ((UINTN) Address >> 12) & PAGING_VTD_INDEX_MASK;=0D
+=0D
+ Is5LevelPaging =3D VtdUnitInfo->Is5LevelPaging;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ L5PageTable =3D (UINT64 *) SecondLevelPagingEntry;=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ L5PageTable[Index5] =3D (UINT64) (UINTN) AllocateZeroPages (1);=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\=
n", Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) L5PageTable[Index5], SIZE=
_4KB);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *=
) &L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE)=
;=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L5PageTable[Index5], siz=
eof(L5PageTable[Index5]));=0D
+ }=0D
+ L4PageTable =3D (UINT64 *) (UINTN) (L5PageTable[Index5] & PAGING_4K_AD=
DRESS_MASK_64);=0D
+ } else {=0D
+ L4PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ L4PageTable[Index4] =3D (UINT64) (UINTN) AllocateZeroPages (1);=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n"=
, Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) L4PageTable[Index4], SIZE_4=
KB);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *) =
&L4PageTable[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L4PageTable[Index4], sizeo=
f(L4PageTable[Index4]));=0D
+ }=0D
+=0D
+ L3PageTable =3D (UINT64 *) (UINTN) (L4PageTable[Index4] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ L3PageTable[Index3] =3D (UINT64) (UINTN) AllocateZeroPages (1);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!=
!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) L3PageTable[Index3], SIZE_4=
KB);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *) =
&L3PageTable[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L3PageTable[Index3], sizeo=
f (L3PageTable[Index3]));=0D
+ }=0D
+ if ((L3PageTable[Index3] & VTD_PG_PS) !=3D 0) {=0D
+ // 1G=0D
+ *PageAttribute =3D Page1G;=0D
+ return &L3PageTable[Index3];=0D
+ }=0D
+=0D
+ L2PageTable =3D (UINT64 *) (UINTN) (L3PageTable[Index3] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ if (L2PageTable[Index2] =3D=3D 0) {=0D
+ L2PageTable[Index2] =3D Address & PAGING_2M_ADDRESS_MASK_64;=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *) =
&L2PageTable[Index2], 0);=0D
+ L2PageTable[Index2] |=3D VTD_PG_PS;=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) &L2PageTable[Index2], sizeo=
f (L2PageTable[Index2]));=0D
+ }=0D
+ if ((L2PageTable[Index2] & VTD_PG_PS) !=3D 0) {=0D
+ // 2M=0D
+ *PageAttribute =3D Page2M;=0D
+ return &L2PageTable[Index2];=0D
+ }=0D
+=0D
+ // 4k=0D
+ L1PageTable =3D (UINT64 *) (UINTN) (L2PageTable[Index2] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ if ((L1PageTable[Index1] =3D=3D 0) && (Address !=3D 0)) {=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ *PageAttribute =3D Page4K;=0D
+ return &L1PageTable[Index1];=0D
+}=0D
+=0D
+/**=0D
+ Modify memory attributes of page entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] PageEntry The page entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[out] IsModified TRUE means page table modified. FALSE mean=
s page table not modified.=0D
+**/=0D
+VOID=0D
+ConvertSecondLevelPageEntryAttribute (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN UINT64 IoMmuAccess,=0D
+ OUT BOOLEAN *IsModified=0D
+ )=0D
+{=0D
+ UINT64 CurrentPageEntry;=0D
+ UINT64 NewPageEntry;=0D
+=0D
+ CurrentPageEntry =3D PageEntry->Uint64;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN) PageEntry, sizeof(*PageEntry)=
);=0D
+ NewPageEntry =3D PageEntry->Uint64;=0D
+ if (CurrentPageEntry !=3D NewPageEntry) {=0D
+ *IsModified =3D TRUE;=0D
+ DEBUG ((DEBUG_VERBOSE, "ConvertSecondLevelPageEntryAttribute 0x%lx", C=
urrentPageEntry));=0D
+ DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));=0D
+ } else {=0D
+ *IsModified =3D FALSE;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ This function returns if there is need to split page entry.=0D
+=0D
+ @param[in] BaseAddress The base address to be checked.=0D
+ @param[in] Length The length to be checked.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+=0D
+ @retval SplitAttributes on if there is need to split page entry.=0D
+**/=0D
+PAGE_ATTRIBUTE=0D
+NeedSplitPage (=0D
+ IN PHYSICAL_ADDRESS BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINT64 PageEntryLength;=0D
+=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+=0D
+ if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D Pag=
eEntryLength)) {=0D
+ return PageNone;=0D
+ }=0D
+=0D
+ if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) {=0D
+ return Page4K;=0D
+ }=0D
+=0D
+ return Page2M;=0D
+}=0D
+=0D
+/**=0D
+ This function splits one page entry to small page entries.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] PageEntry The page entry to be splitted.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+ @param[in] SplitAttribute How to split the page entry.=0D
+=0D
+ @retval RETURN_SUCCESS The page entry is splitted.=0D
+ @retval RETURN_UNSUPPORTED The page entry does not support to be =
splitted.=0D
+ @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.=0D
+**/=0D
+RETURN_STATUS=0D
+SplitSecondLevelPage (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN PAGE_ATTRIBUTE PageAttribute,=0D
+ IN PAGE_ATTRIBUTE SplitAttribute=0D
+ )=0D
+{=0D
+ UINT64 BaseAddress;=0D
+ UINT64 *NewPageEntry;=0D
+ UINTN Index;=0D
+=0D
+ ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G);=0D
+=0D
+ if (PageAttribute =3D=3D Page2M) {=0D
+ //=0D
+ // Split 2M to 4K=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page4K);=0D
+ if (SplitAttribute =3D=3D Page4K) {=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_INFO, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_2M_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | (PageEn=
try->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)PageEntry, sizeof(*PageEnt=
ry));=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else if (PageAttribute =3D=3D Page1G) {=0D
+ //=0D
+ // Split 1G to 2M=0D
+ // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K =
to get more compact page table.=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K);=
=0D
+ if ((SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K)) {=
=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_INFO, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_1G_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | VTD_PG_=
PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdUnitInfo, (UINTN)PageEntry, sizeof(*PageEnt=
ry));=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory on second level page entry=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetSecondLevelPagingAttribute (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry;=0D
+ PAGE_ATTRIBUTE PageAttribute;=0D
+ UINTN PageEntryLength;=0D
+ PAGE_ATTRIBUTE SplitAttribute;=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN IsEntryModified;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "SetSecondLevelPagingAttribute (0x%016lx - 0x%016lx =
: %x) \n", BaseAddress, Length, IoMmuAccess));=0D
+ DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry Base - 0x%x\n", SecondLeve=
lPagingEntry));=0D
+=0D
+ if (BaseAddress !=3D ALIGN_VALUE(BaseAddress, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ if (Length !=3D ALIGN_VALUE(Length, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ while (Length !=3D 0) {=0D
+ PageEntry =3D GetSecondLevelPageTableEntry (VtdUnitInfo, SecondLevelPa=
gingEntry, BaseAddress, &PageAttribute);=0D
+ if (PageEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+ SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageAttribute);=
=0D
+ if (SplitAttribute =3D=3D PageNone) {=0D
+ ConvertSecondLevelPageEntryAttribute (VtdUnitInfo, PageEntry, IoMmuA=
ccess, &IsEntryModified);=0D
+ //=0D
+ // Convert success, move to next=0D
+ //=0D
+ BaseAddress +=3D PageEntryLength;=0D
+ Length -=3D PageEntryLength;=0D
+ } else {=0D
+ Status =3D SplitSecondLevelPage (VtdUnitInfo, PageEntry, PageAttribu=
te, SplitAttribute);=0D
+ if (RETURN_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ //=0D
+ // Just split current page=0D
+ // Convert success in next around=0D
+ //=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create Fixed Second Level Paging Entry.=0D
+=0D
+ @param[in] VtdUnitInfo The VTd engine unit information.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCES Setup translation table fail.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+CreateFixedSecondLevelPagingEntry (=0D
+ IN VTD_UNIT_INFO *VtdUnitInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT64 IoMmuAccess;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 Length;=0D
+ VOID *Hob;=0D
+ DMA_BUFFER_INFO *DmaBufferInfo;=0D
+=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry !=3D 0) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ VtdUnitInfo->FixedSecondLevelPagingEntry =3D (UINTN) CreateSecondLevelPa=
gingEntryTable (VtdUnitInfo, NULL, 0, SIZE_4GB, 0);=0D
+ if (VtdUnitInfo->FixedSecondLevelPagingEntry =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid);=0D
+ DmaBufferInfo =3D GET_GUID_HOB_DATA (Hob);=0D
+ BaseAddress =3D DmaBufferInfo->DmaBufferBase;=0D
+ Length =3D DmaBufferInfo->DmaBufferSize;=0D
+ IoMmuAccess =3D EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " BaseAddress =3D 0x%lx\n", BaseAddress));=0D
+ DEBUG ((DEBUG_INFO, " Length =3D 0x%lx\n", Length));=0D
+ DEBUG ((DEBUG_INFO, " IoMmuAccess =3D 0x%lx\n", IoMmuAccess));=0D
+=0D
+ Status =3D SetSecondLevelPagingAttribute (VtdUnitInfo, (VTD_SECOND_LEVEL=
_PAGING_ENTRY*) VtdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Leng=
th, IoMmuAccess);=0D
+=0D
+ return Status;=0D
+}=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @param[in] VTdInfo The VTd engine context information.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCES Setup translation table fail.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ IN VTD_INFO *VTdInfo=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ VTD_UNIT_INFO *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) {=0D
+ VtdUnitInfo =3D &VTdInfo->VtdUnitInfo[Index];=0D
+ if (VtdUnitInfo->Done) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Status =3D CreateFixedSecondLevelPagingEntry (VtdUnitInfo);=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_INFO, "CreateFixedSecondLevelPagingEntry failed - %r\n=
", Status));=0D
+ return Status;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ECapReg.Bits.SMTS) {=0D
+ if (VtdUnitInfo->ECapReg.Bits.DEP_24) {=0D
+ DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));=0D
+ ASSERT(FALSE);=0D
+ Status =3D EFI_UNSUPPORTED;=0D
+ } else {=0D
+ Status =3D CreateContextEntry (VtdUnitInfo);=0D
+ }=0D
+ } else {=0D
+ if (VtdUnitInfo->ECapReg.Bits.DEP_24) {=0D
+ //=0D
+ // To compatible with pervious VTd engine=0D
+ // It was ECS(Extended Context Support) bit.=0D
+ //=0D
+ Status =3D CreateExtContextEntry (VtdUnitInfo);=0D
+ } else {=0D
+ Status =3D CreateContextEntry (VtdUnitInfo);=0D
+ }=0D
+ }=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHob.h b/S=
ilicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHob.h
new file mode 100644
index 000000000..cfddce995
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHob.h
@@ -0,0 +1,151 @@
+/** @file=0D
+ The definition for VTD Log Data Hob.=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+**/=0D
+=0D
+=0D
+#ifndef _VTD_LOG_DATA_HOB_H_=0D
+#define _VTD_LOG_DATA_HOB_H_=0D
+=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+#define VTDLOG_LOG_TYPE(_id_) ((UINT64) 1 << (_id_))=0D
+=0D
+typedef enum {=0D
+ VTDLOG_PEI_BASIC =3D 0, // Start ID for PEI bas=
ic log=0D
+ VTDLOG_PEI_PRE_MEM_DMA_PROTECT =3D 1, // PRE-MEM phase=0D
+ VTDLOG_PEI_PMR_LOW_MEMORY_RANGE =3D 2,=0D
+ VTDLOG_PEI_PMR_HIGH_MEMORY_RANGE =3D 3,=0D
+ VTDLOG_PEI_PROTECT_MEMORY_RANGE =3D 4,=0D
+ VTDLOG_PEI_POST_MEM_ENABLE_DMA_PROTECT =3D 5,=0D
+ VTDLOG_PEI_POST_MEM_DISABLE_DMA_PROTECT =3D 6,=0D
+ VTDLOG_PEI_QUEUED_INVALIDATION =3D 7,=0D
+ VTDLOG_PEI_REGISTER =3D 8,=0D
+ VTDLOG_PEI_VTD_ERROR =3D 9,=0D
+=0D
+ VTDLOG_PEI_ADVANCED =3D 16, // Start ID for PEI ad=
vanced log=0D
+ VTDLOG_PEI_PPI_ALLOC_BUFFER =3D 17,=0D
+ VTDLOG_PEI_PPI_MAP =3D 18,=0D
+=0D
+ VTDLOG_DXE_BASIC =3D 24, // Start ID for DXE ba=
sic log=0D
+ VTDLOG_DXE_DMAR_TABLE =3D 25,=0D
+ VTDLOG_DXE_SETUP_VTD =3D 26,=0D
+ VTDLOG_DXE_PCI_DEVICE =3D 27,=0D
+ VTDLOG_DXE_REGISTER =3D 28,=0D
+ VTDLOG_DXE_ENABLE_DMAR =3D 29,=0D
+ VTDLOG_DXE_DISABLE_DMAR =3D 30,=0D
+ VTDLOG_DXE_DISABLE_PMR =3D 31,=0D
+ VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL =3D 32,=0D
+ VTDLOG_DXE_QUEUED_INVALIDATION =3D 33, =0D
+=0D
+ VTDLOG_DXE_ADVANCED =3D 44, // Start ID for DXE ad=
vanced log=0D
+ VTDLOG_DXE_IOMMU_ALLOC_BUFFER =3D 45,=0D
+ VTDLOG_DXE_IOMMU_FREE_BUFFER =3D 46,=0D
+ VTDLOG_DXE_IOMMU_MAP =3D 47,=0D
+ VTDLOG_DXE_IOMMU_UNMAP =3D 48,=0D
+ VTDLOG_DXE_IOMMU_SET_ATTRIBUTE =3D 49,=0D
+ VTDLOG_DXE_ROOT_TABLE =3D 50,=0D
+} VTDLOG_EVENT_TYPE;=0D
+=0D
+#define VTD_LOG_PEI_PRE_MEM_BAR_MAX 8=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_BASIC / VTDLOG_DXE_BASIC=0D
+//=0D
+#define VTD_LOG_ERROR_BUFFER_FULL (1<<0)=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_PRE_MEM_DMA_PROTECT_MODE=0D
+//=0D
+#define VTD_LOG_PEI_PRE_MEM_NOT_USED 0=0D
+#define VTD_LOG_PEI_PRE_MEM_DISABLE 1=0D
+#define VTD_LOG_PEI_PRE_MEM_ADM 2=0D
+#define VTD_LOG_PEI_PRE_MEM_TE 3=0D
+#define VTD_LOG_PEI_PRE_MEM_PMR 4=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_QUEUED_INVALIDATION=0D
+//=0D
+#define VTD_LOG_QI_DISABLE 0=0D
+#define VTD_LOG_QI_ENABLE 1=0D
+#define VTD_LOG_QI_ERROR_OUT_OF_RESOURCES 2=0D
+=0D
+//=0D
+// Code of VTDLOG_PEI_VTD_ERROR=0D
+//=0D
+#define VTD_LOG_PEI_VTD_ERROR_PPI_ALLOC 1=0D
+#define VTD_LOG_PEI_VTD_ERROR_PPI_MAP 2=0D
+=0D
+// Code of VTDLOG_PEI_REGISTER / VTDLOG_DXE_REGISTER=0D
+#define VTDLOG_REGISTER_ALL 0=0D
+#define VTDLOG_REGISTER_THIN 1=0D
+#define VTDLOG_REGISTER_QI 2=0D
+=0D
+#pragma pack(1)=0D
+=0D
+//=0D
+// Item head=0D
+//=0D
+typedef struct {=0D
+ UINT32 DataSize;=0D
+ UINT64 LogType;=0D
+ UINT64 Timestamp;=0D
+}VTDLOG_EVENT_HEADER;=0D
+=0D
+//=0D
+// Struct for type =3D VTDLOG_PEI_REGISTER=0D
+// VTDLOG_DXE_REGISTER=0D
+// VTDLOG_DXE_DMAR_TABLE=0D
+// VTDLOG_DXE_IOMMU_SET_ATTRIBUTE=0D
+// VTDLOG_DXE_PCI_DEVICE=0D
+// VTDLOG_DXE_ROOT_TABLE=0D
+//=0D
+typedef struct {=0D
+ VTDLOG_EVENT_HEADER Header;=0D
+ UINT64 Param;=0D
+ UINT8 Data[1];=0D
+} VTDLOG_EVENT_CONTEXT;=0D
+=0D
+//=0D
+// Struct for rest of the types=0D
+//=0D
+typedef struct {=0D
+ VTDLOG_EVENT_HEADER Header;=0D
+ UINT64 Data1;=0D
+ UINT64 Data2;=0D
+}VTDLOG_EVENT_2PARAM;=0D
+=0D
+//=0D
+// Struct for VTd log event=0D
+//=0D
+typedef union{=0D
+ VTDLOG_EVENT_HEADER EventHeader;=0D
+ VTDLOG_EVENT_2PARAM CommenEvent;=0D
+ VTDLOG_EVENT_CONTEXT ContextEvent;=0D
+} VTDLOG_EVENT;=0D
+=0D
+//=0D
+// Information for PEI pre-memory phase=0D
+//=0D
+typedef struct {=0D
+ UINT8 Mode;=0D
+ UINT8 Status;=0D
+ UINT32 BarAddress;=0D
+} VTDLOG_PEI_PRE_MEM_INFO;=0D
+=0D
+//=0D
+// Buffer struct for PEI phase=0D
+//=0D
+typedef struct {=0D
+ UINT8 VtdLogPeiError;=0D
+ VTDLOG_PEI_PRE_MEM_INFO PreMemInfo[VTD_LOG_PEI_PRE_MEM_BAR_MAX];=0D
+ UINT32 PostMemBufferUsed;=0D
+ UINT64 PostMemBuffer;=0D
+} VTDLOG_PEI_BUFFER_HOB;=0D
+=0D
+#pragma pack()=0D
+=0D
+#endif // _VTD_LOG_DATA_HOB_H_=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdPeiDxeLi=
b.h b/Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdPeiDxeLib.h
new file mode 100644
index 000000000..c0a137a77
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdPeiDxeLib.h
@@ -0,0 +1,329 @@
+/** @file=0D
+ Intel VTd library definitions.=0D
+=0D
+ Copyright (c) 2023 Intel Corporation. All rights reserved. <BR>=0D
+=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+**/=0D
+#ifndef _INTEL_VTD_PEI_DXE_LIB_H_=0D
+#define _INTEL_VTD_PEI_DXE_LIB_H_=0D
+=0D
+//=0D
+// Include files=0D
+//=0D
+#include <Uefi/UefiBaseType.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Protocol/VtdLog.h>=0D
+#include <Protocol/PlatformVtdPolicy.h>=0D
+=0D
+#if defined (EXT_CALLBACK)=0D
+ #define _VTDLIB_DEBUG(PrintLevel, ...) =
\=0D
+ do { =
\=0D
+ VtdLogEventCallback (Context, CallbackHandle, PrintLevel, ##__VA_ARG=
S__); \=0D
+ } while (FALSE)=0D
+ #define VTDLIB_DEBUG(Expression) _VTDLIB_DEBUG Expression=0D
+#else=0D
+ #define VTDLIB_DEBUG(Expression) DEBUG(Expression)=0D
+#endif=0D
+=0D
+#pragma pack(1)=0D
+=0D
+typedef struct {=0D
+ UINT8 DeviceType;=0D
+ VTD_SOURCE_ID PciSourceId;=0D
+ EDKII_PLATFORM_VTD_PCI_DEVICE_ID PciDeviceId;=0D
+ // for statistic analysis=0D
+ UINT64 AccessCount;=0D
+} PCI_DEVICE_DATA;=0D
+=0D
+typedef struct {=0D
+ BOOLEAN IncludeAllFlag;=0D
+ UINT16 Segment;=0D
+ UINT32 PciDeviceDataMaxNumber;=0D
+ UINT32 PciDeviceDataNumber;=0D
+ PCI_DEVICE_DATA PciDeviceData[1];=0D
+} PCI_DEVICE_INFORMATION;=0D
+=0D
+typedef struct {=0D
+ UINT64 Uint64Lo;=0D
+ UINT64 Uint64Hi;=0D
+}VTD_UINT128;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT32 VerReg;=0D
+ UINT64 CapReg;=0D
+ UINT64 EcapReg;=0D
+ UINT32 GstsReg;=0D
+ UINT64 RtaddrReg;=0D
+ UINT64 CcmdReg;=0D
+ UINT32 FstsReg;=0D
+ UINT32 FectlReg;=0D
+ UINT32 FedataReg;=0D
+ UINT32 FeaddrReg;=0D
+ UINT32 FeuaddrReg;=0D
+ UINT64 IqercdReg;=0D
+ UINT64 IvaReg;=0D
+ UINT64 IotlbReg;=0D
+ UINT16 FrcdRegNum; // Number of FRCD Register=
s=0D
+ VTD_UINT128 FrcdReg[1];=0D
+} VTD_REGESTER_INFO;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT32 FstsReg;=0D
+ UINT64 IqercdReg;=0D
+} VTD_REGESTER_QI_INFO;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT32 GstsReg;=0D
+ UINT64 RtaddrReg;=0D
+ UINT32 FstsReg;=0D
+ UINT32 FectlReg;=0D
+ UINT64 IqercdReg;=0D
+ UINT16 FrcdRegNum; // Number of FRCD Register=
s=0D
+ VTD_UINT128 FrcdReg[1];=0D
+} VTD_REGESTER_THIN_INFO;=0D
+=0D
+typedef struct {=0D
+ VTD_SOURCE_ID SourceId;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ UINT64 Length;=0D
+ UINT64 IoMmuAccess;=0D
+ EFI_STATUS Status;=0D
+} VTD_PROTOCOL_SET_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ UINT64 BaseAddress;=0D
+ UINT64 TableAddress;=0D
+ BOOLEAN Is5LevelPaging;=0D
+} VTD_ROOT_TABLE_INFO;=0D
+=0D
+#pragma pack()=0D
+=0D
+/**=0D
+ Callback function of VTd lib handle strings.=0D
+=0D
+ @param[in] Context Context=0D
+ @param[in] ErrorLevel The error level of the debug message.=
=0D
+ @param[in] Buffer Event string=0D
+**/=0D
+typedef=0D
+VOID=0D
+(EFIAPI *EDKII_VTD_LIB_STRING_CB) (=0D
+ IN VOID *Context,=0D
+ IN UINTN ErrorLevel,=0D
+ IN CHAR8 *Buffer=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event Context=0D
+ @param[in out] CallbackHandle Callback Handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmar (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ );=0D
+=0D
+/**=0D
+ Dump DRHD DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event Context=0D
+ @param[in out] CallbackHandle Callback Handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmarDrhd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ );=0D
+=0D
+/**=0D
+ Dump the PCI device information managed by this VTd engine.=0D
+=0D
+ @param[in] Context Event Context=0D
+ @param[in out] CallbackHandle Callback Handler=0D
+ @param[in] PciDeviceInfo PCI device information=0D
+**/=0D
+VOID=0D
+VtdLibDumpPciDeviceInfo (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN PCI_DEVICE_INFORMATION *PciDeviceInfo=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] RootEntry DMAR root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_ROOT_ENTRY *RootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ );=0D
+=0D
+/**=0D
+ Dump DMAR extended context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] ExtRootEntry DMAR extended root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarExtContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers Information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsAll (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_INFO *VtdRegInfo=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers Information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsThin (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_THIN_INFO *VtdRegInfo=0D
+ );=0D
+=0D
+/**=0D
+ Decode log event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event Event struct=0D
+=0D
+ @retval TRUE Decode event success=0D
+ @retval FALSE Unknown event=0D
+**/=0D
+BOOLEAN=0D
+VtdLibDecodeEvent (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT *Event=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTd engine write buffer.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibFlushWriteBuffer (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Clear Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask.=0D
+**/=0D
+VOID=0D
+VtdLibClearGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ );=0D
+=0D
+/**=0D
+ Set Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask.=0D
+**/=0D
+VOID=0D
+VtdLibSetGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ );=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisableDmar (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Disable PMR.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS PMR is disabled.=0D
+ @retval EFI_UNSUPPORTED PMR is not supported.=0D
+ @retval EFI_NOT_STARTED PMR was not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisablePmr (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Disable queued invalidation interface.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibDisableQueuedInvalidationInterface (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+ @param[in] ClearFaultBits Clear Error bits=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+ @retval EFI_DEVICE_ERROR Detect fault, need to clear fault bits=
if ClearFaultBits is FALSE=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibSubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN VOID *Desc,=0D
+ IN BOOLEAN ClearFaultBits=0D
+ );=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h b/Sili=
con/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
new file mode 100644
index 000000000..7c2894e81
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
@@ -0,0 +1,59 @@
+/** @file=0D
+ The definition for VTD Log.=0D
+=0D
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef __VTD_LOG_PROTOCOL_H__=0D
+#define __VTD_LOG_PROTOCOL_H__=0D
+=0D
+#include <Guid/VtdLogDataHob.h>=0D
+=0D
+#define EDKII_VTD_LOG_PROTOCOL_GUID \=0D
+ { \=0D
+ 0x1e271819, 0xa3ca, 0x481f, { 0xbd, 0xff, 0x92, 0x78, 0x2f, 0x9a, 0x=
99, 0x3c } \=0D
+ }=0D
+=0D
+typedef struct _EDKII_VTD_LOG_PROTOCOL EDKII_VTD_LOG_PROTOCOL;=0D
+=0D
+#define EDKII_VTD_LOG_PROTOCOL_REVISION 0x00010000=0D
+=0D
+/**=0D
+ Callback function of each VTd log event.=0D
+ @param[in] Context Event context=0D
+ @param[in] Header Event header=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+typedef=0D
+VOID=0D
+(EFIAPI *EDKII_VTD_LOG_HANDLE_EVENT) (=0D
+ IN VOID *Context,=0D
+ IN VTDLOG_EVENT_HEADER *Header=0D
+ );=0D
+=0D
+/**=0D
+ Get the VTd log events.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+typedef=0D
+UINT64=0D
+(EFIAPI *EDKII_VTD_LOG_GET_EVENTS) (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ );=0D
+=0D
+struct _EDKII_VTD_LOG_PROTOCOL {=0D
+ UINT64 Revision;=0D
+ EDKII_VTD_LOG_GET_EVENTS GetEvents;=0D
+};=0D
+=0D
+extern EFI_GUID gEdkiiVTdLogProtocolGuid;=0D
+=0D
+#endif=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/In=
tel/IntelSiliconPkg/IntelSiliconPkg.dec
index cad22acda..ec8690a8d 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -73,6 +73,9 @@
## HOB GUID to get memory information after MRC is done. The hob data wi=
ll be used to set the PMR ranges=0D
gVtdPmrInfoDataHobGuid =3D {0x6fb61645, 0xf168, 0x46be, { 0x80, 0xec, 0x=
b5, 0x02, 0x38, 0x5e, 0xe7, 0xe7 } }=0D
=0D
+ ## HOB GUID to get VTd log data.=0D
+ gVTdLogBufferHobGuid =3D {0xc8049121, 0xdf91, 0x4dfd, { 0xad, 0xcb, 0x1c=
, 0x55, 0x85, 0x09, 0x6d, 0x3b } }=0D
+=0D
## Include/Guid/MicrocodeShadowInfoHob.h=0D
gEdkiiMicrocodeShadowInfoHobGuid =3D { 0x658903f9, 0xda66, 0x460d, { 0x8=
b, 0xb0, 0x9d, 0x2d, 0xdf, 0x65, 0x44, 0x59 } }=0D
=0D
@@ -119,6 +122,8 @@
gPchSmmSpi2ProtocolGuid =3D { 0x2d1c0c43, 0x20d3, 0x40ae, { 0x99, 0x07, =
0x2d, 0xf0, 0xe7, 0x91, 0x21, 0xa5 } }=0D
=0D
gEdkiiPlatformVTdPolicyProtocolGuid =3D { 0x3d17e448, 0x466, 0x4e20, { 0=
x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }}=0D
+ gEdkiiVTdLogProtocolGuid =3D { 0x1e271819, 0xa3ca, 0x481f, { 0xbd, 0xff,=
0x92, 0x78, 0x2f, 0x9a, 0x99, 0x3c }}=0D
+=0D
gIntelDieInfoProtocolGuid =3D { 0xAED8A0A1, 0xFDE6, 0x4CF2, { 0xA3, 0x85=
, 0x08, 0xF1, 0x25, 0xF2, 0x40, 0x37 }}=0D
=0D
## Protocol for device security policy.=0D
@@ -207,3 +212,19 @@
# non-zero: The size of an additional NVS region following the Regular =
variable region.<BR>=0D
# @Prompt Additional NVS Region Size.=0D
gIntelSiliconPkgTokenSpaceGuid.PcdFlashNvStorageAdditionalSize|0x0000000=
0|UINT32|0x0000000F=0D
+=0D
+ ## Declares VTd LOG Output Level.<BR><BR>=0D
+ # 0 : Disable VTd Log=0D
+ # 1 : Enable Basic Log=0D
+ # 2 : Enable All Log=0D
+ # @Prompt The VTd Log Output Level.=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel|0x02|UINT8|0x00000017=0D
+=0D
+ ## Declares VTd PEI POST-MEM LOG buffer size.<BR><BR>=0D
+ # @Prompt The VTd PEI Post-Mem Log buffer size. 8k=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize|0x00002000|=
UINT32|0x00000019=0D
+=0D
+ ## Declares VTd DXE LOG buffer size.<BR><BR>=0D
+ # @Prompt The VTd DXE Log buffer size. 4M=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdDxeLogBufferSize|0x00400000|UINT32|=
0x0000001A=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc b/Silicon/In=
tel/IntelSiliconPkg/IntelSiliconPkg.dsc
index 170eb480a..c8ff40b38 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dsc
@@ -45,6 +45,7 @@
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBoo=
tServicesTableLib.inf=0D
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntry=
Point.inf=0D
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseV=
ariableFlashInfoLib.inf=0D
+ IntelVTdPeiDxeLib|IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiD=
xeLib.inf=0D
=0D
[LibraryClasses.common.PEIM]=0D
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelV=
TdPeiDxeLib.c b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/Int=
elVTdPeiDxeLib.c
new file mode 100644
index 000000000..67953202b
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiDx=
eLib.c
@@ -0,0 +1,1819 @@
+/** @file=0D
+ Source code file for Intel VTd PEI DXE library.=0D
+=0D
+Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+//=0D
+// Define the maximum message length that this library supports=0D
+//=0D
+#define MAX_STRING_LENGTH (0x100)=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+/**=0D
+ Produces a Null-terminated ASCII string in an output buffer based on a N=
ull-terminated=0D
+ ASCII format string and variable argument list.=0D
+ =0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] ErrorLevel The error level of the debug message.=0D
+ @param[in] FormatString A Null-terminated ASCII format string.=
=0D
+ @param[in] ... Variable argument list whose contents a=
re accessed based on the format string specified by FormatString.=0D
+=0D
+ @return The number of ASCII characters in the produced output buffer not=
including the=0D
+ Null-terminator.=0D
+**/=0D
+UINTN=0D
+EFIAPI=0D
+VtdLogEventCallback (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN UINTN ErrorLevel,=0D
+ IN CONST CHAR8 *FormatString,=0D
+ ...=0D
+ )=0D
+{=0D
+ CHAR8 Buffer[MAX_STRING_LENGTH];=0D
+ VA_LIST Marker;=0D
+ UINTN NumberOfPrinted;=0D
+=0D
+ if ((CallbackHandle =3D=3D NULL) || (FormatString =3D=3D NULL)) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ VA_START (Marker, FormatString);=0D
+ NumberOfPrinted =3D AsciiVSPrint (Buffer, sizeof (Buffer), FormatString,=
Marker);=0D
+ VA_END (Marker);=0D
+=0D
+ if (NumberOfPrinted > 0) {=0D
+ CallbackHandle (Context, ErrorLevel, Buffer);=0D
+ }=0D
+=0D
+ return NumberOfPrinted;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR DeviceScopeEntry.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarDeviceScopeEntry (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntr=
y=0D
+ )=0D
+{=0D
+ UINTN PciPathNumber;=0D
+ UINTN PciPathIndex;=0D
+ EFI_ACPI_DMAR_PCI_PATH *PciPath;=0D
+=0D
+ if (DmarDeviceScopeEntry =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " * DMA-Remapping Device Scope Entry Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *****************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " DMAR Device Scope Entry address ...................... 0x%016lx\n=
" :=0D
+ " DMAR Device Scope Entry address ...................... 0x%08x\n",=
=0D
+ DmarDeviceScopeEntry=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Device Scope Entry Type ............................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Type=0D
+ ));=0D
+ switch (DmarDeviceScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " PCI Endpoint Device\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " PCI Sub-hierachy\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " IOAPIC\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " MSI Capable HPET\n"=0D
+ ));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " ACPI Namespace Device\n"=0D
+ ));=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................. 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Enumeration ID ..................................... 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->EnumerationId=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Starting Bus Number ................................ 0x%02x\n",=
=0D
+ DmarDeviceScopeEntry->StartBusNumber=0D
+ ));=0D
+=0D
+ PciPathNumber =3D (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_D=
EVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);=0D
+ PciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);=0D
+ for (PciPathIndex =3D 0; PciPathIndex < PciPathNumber; PciPathIndex++) {=
=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Device ............................................. 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Device=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Function ........................................... 0x%02x\n=
",=0D
+ PciPath[PciPathIndex].Function=0D
+ ));=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *****************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR SIDP table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Sidp DMAR SIDP table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarSidp (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_SIDP_HEADER *Sidp=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN SidpLen;=0D
+=0D
+ if (Sidp =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " * SoC Integrated Device Property Reporting Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " SIDP address ........................................... 0x%016lx\n=
" :=0D
+ " SIDP address ........................................... 0x%08x\n",=
=0D
+ Sidp=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Sidp->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Sidp->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Sidp->SegmentNumber=0D
+ ));=0D
+=0D
+ SidpLen =3D Sidp->Header.Length - sizeof(EFI_ACPI_DMAR_SIDP_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Sidp + 1);=0D
+ while (SidpLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ SidpLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR SATC table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Satc DMAR SATC table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarSatc (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_SATC_HEADER *Satc=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN SatcLen;=0D
+=0D
+ if (Satc =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * ACPI Soc Integrated Address Translation Cache reporting Str=
ucture *\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " SATC address ........................................... 0x%016lx\n=
" :=0D
+ " SATC address ........................................... 0x%08x\n",=
=0D
+ Satc=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Satc->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Satc->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Satc->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Satc->SegmentNumber=0D
+ ));=0D
+=0D
+ SatcLen =3D Satc->Header.Length - sizeof(EFI_ACPI_DMAR_SATC_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Satc + 1);=0D
+ while (SatcLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ SatcLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ANDD table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Andd DMAR ANDD table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarAndd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_ANDD_HEADER *Andd=0D
+ )=0D
+{=0D
+ if (Andd =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * ACPI Name-space Device Declaration Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " ANDD address ........................................... 0x%016lx\n=
" :=0D
+ " ANDD address ........................................... 0x%08x\n",=
=0D
+ Andd=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Andd->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Andd->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " ACPI Device Number ................................... 0x%02x\n",=
=0D
+ Andd->AcpiDeviceNumber=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " ACPI Object Name ..................................... '%a'\n",=0D
+ (Andd + 1)=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR RHSA table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Rhsa DMAR RHSA table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarRhsa (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_RHSA_HEADER *Rhsa=0D
+ )=0D
+{=0D
+ if (Rhsa =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * Remapping Hardware Status Affinity Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " RHSA address ........................................... 0x%016lx\n=
" :=0D
+ " RHSA address ........................................... 0x%08x\n",=
=0D
+ Rhsa=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Rhsa->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Rhsa->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Register Base Address ................................ 0x%016lx\n=
",=0D
+ Rhsa->RegisterBaseAddress=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Proximity Domain ..................................... 0x%08x\n",=
=0D
+ Rhsa->ProximityDomain=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ATSR table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Atsr DMAR ATSR table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarAtsr (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_ATSR_HEADER *Atsr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN AtsrLen;=0D
+=0D
+ if (Atsr =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * Root Port ATS Capability Reporting Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " ATSR address ........................................... 0x%016lx\n=
" :=0D
+ " ATSR address ........................................... 0x%08x\n",=
=0D
+ Atsr=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Atsr->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Atsr->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Atsr->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " ALL_PORTS .......................................... 0x%02x\n",=
=0D
+ Atsr->Flags & EFI_ACPI_DMAR_ATSR_FLAGS_ALL_PORTS=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Atsr->SegmentNumber=0D
+ ));=0D
+=0D
+ AtsrLen =3D Atsr->Header.Length - sizeof(EFI_ACPI_DMAR_ATSR_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Atsr + 1);=0D
+ while (AtsrLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ AtsrLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR RMRR table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Rmrr DMAR RMRR table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarRmrr (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN RmrrLen;=0D
+=0D
+ if (Rmrr =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * Reserved Memory Region Reporting Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " RMRR address ........................................... 0x%016lx\n=
" :=0D
+ " RMRR address ........................................... 0x%08x\n",=
=0D
+ Rmrr=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Rmrr->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Rmrr->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Rmrr->SegmentNumber=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Reserved Memory Region Base Address .................. 0x%016lx\n=
",=0D
+ Rmrr->ReservedMemoryRegionBaseAddress=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Reserved Memory Region Limit Address ................. 0x%016lx\n=
",=0D
+ Rmrr->ReservedMemoryRegionLimitAddress=0D
+ ));=0D
+=0D
+ RmrrLen =3D Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Rmrr + 1);=0D
+ while (RmrrLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ RmrrLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR DRHD table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Drhd DMAR DRHD table=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarDrhd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;=0D
+ INTN DrhdLen;=0D
+=0D
+ if (Drhd =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " * DMA-Remapping Hardware Definition Structure =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " *******************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ " DRHD address ........................................... 0x%016lx\n=
" :=0D
+ " DRHD address ........................................... 0x%08x\n",=
=0D
+ Drhd=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Type ................................................. 0x%04x\n",=
=0D
+ Drhd->Header.Type=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Length ............................................... 0x%04x\n",=
=0D
+ Drhd->Header.Length=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, =0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Drhd->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " INCLUDE_PCI_ALL .................................... 0x%02x\n",=
=0D
+ Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Size ................................................. 0x%02x\n",=
=0D
+ Drhd->Size=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Segment Number ....................................... 0x%04x\n",=
=0D
+ Drhd->SegmentNumber=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Register Base Address ................................ 0x%016lx\n=
",=0D
+ Drhd->RegisterBaseAddress=0D
+ ));=0D
+=0D
+ DrhdLen =3D Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)=
(Drhd + 1);=0D
+ while (DrhdLen > 0) {=0D
+ VtdLibDumpDmarDeviceScopeEntry (Context, CallbackHandle, DmarDeviceSco=
peEntry);=0D
+ DrhdLen -=3D DmarDeviceScopeEntry->Length;=0D
+ DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER =
*)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " *******************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump Header of DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmarHeader (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "* DMAR Table =
*\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n"=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ (sizeof(UINTN) =3D=3D sizeof(UINT64)) ?=0D
+ "DMAR address ............................................. 0x%016lx\n=
" :=0D
+ "DMAR address ............................................. 0x%08x\n",=
=0D
+ Dmar=0D
+ ));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Table Contents:\n"=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Host Address Width ................................... 0x%02x\n",=
=0D
+ Dmar->HostAddressWidth=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " Flags ................................................ 0x%02x\n",=
=0D
+ Dmar->Flags=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " INTR_REMAP ......................................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT=0D
+ ));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ " DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",=
=0D
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmar (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ INTN DmarLen;=0D
+=0D
+ if (Dmar =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ VtdLibDumpAcpiDmarHeader (Context, CallbackHandle, Dmar);=0D
+=0D
+ DmarLen =3D Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);=0D
+ while (DmarLen > 0) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdLibDumpDmarDrhd (Context, CallbackHandle, (EFI_ACPI_DMAR_DRHD_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_RMRR:=0D
+ VtdLibDumpDmarRmrr (Context, CallbackHandle, (EFI_ACPI_DMAR_RMRR_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_ATSR:=0D
+ VtdLibDumpDmarAtsr (Context, CallbackHandle, (EFI_ACPI_DMAR_ATSR_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_RHSA:=0D
+ VtdLibDumpDmarRhsa (Context, CallbackHandle, (EFI_ACPI_DMAR_RHSA_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_ANDD:=0D
+ VtdLibDumpDmarAndd (Context, CallbackHandle, (EFI_ACPI_DMAR_ANDD_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_SATC:=0D
+ VtdLibDumpDmarSatc (Context, CallbackHandle, (EFI_ACPI_DMAR_SATC_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ case EFI_ACPI_DMAR_TYPE_SIDP:=0D
+ VtdLibDumpDmarSidp (Context, CallbackHandle, (EFI_ACPI_DMAR_SIDP_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarLen -=3D DmarHeader->Length;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump DRHD DMAR ACPI table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Dmar DMAR ACPI table=0D
+**/=0D
+VOID=0D
+VtdLibDumpAcpiDmarDrhd (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN EFI_ACPI_DMAR_HEADER *Dmar=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ INTN DmarLen;=0D
+=0D
+ if (Dmar =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // Dump Dmar table=0D
+ //=0D
+ VtdLibDumpAcpiDmarHeader (Context, CallbackHandle, Dmar);=0D
+=0D
+ DmarLen =3D Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);=0D
+ while (DmarLen > 0) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdLibDumpDmarDrhd (Context, CallbackHandle, (EFI_ACPI_DMAR_DRHD_HEA=
DER *)DmarHeader);=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarLen -=3D DmarHeader->Length;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO,=0D
+ "*********************************************************************=
********\n\n"=0D
+ ));=0D
+}=0D
+=0D
+/**=0D
+ Dump the PCI device information managed by this VTd engine.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] PciDeviceInfo VTd Unit Information=0D
+**/=0D
+VOID=0D
+VtdLibDumpPciDeviceInfo (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN PCI_DEVICE_INFORMATION *PciDeviceInfo=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+=0D
+ if (PciDeviceInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PCI Device Information (Number 0x%x, Inclu=
deAll - %d):\n",=0D
+ PciDeviceInfo->PciDeviceDataNumber,=0D
+ PciDeviceInfo->IncludeAllFlag=0D
+ ));=0D
+ for (Index =3D 0; Index < PciDeviceInfo->PciDeviceDataNumber; Index++)=
{=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " S%04x B%02x D%02x F%02x\n",=0D
+ PciDeviceInfo->Segment,=0D
+ PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.Bus,=0D
+ PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.Device,=0D
+ PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.Function=0D
+ ));=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR second level paging entry.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in] CallbackHandle Callback handler=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpSecondLevelPagingEntry (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VOID *SecondLevelPagingEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Index1;=0D
+ UINTN Lvl5IndexEnd;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl1PtEntry;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "DMAR Second Level Page Table:\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "SecondLevelPagingEntry Base - 0x%x, Is5Le=
velPaging - %d\n", SecondLevelPagingEntry, Is5LevelPaging));=0D
+=0D
+ Lvl5IndexEnd =3D Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY) : 1;=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+=0D
+ for (Index5 =3D 0; Index5 < Lvl5IndexEnd; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl5Pt Entry(0x%03x) - 0x%016lx\n=
", Index5, Lvl5PtEntry[Index5].Uint64));=0D
+ }=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_EN=
TRY); Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl4Pt Entry(0x%03x) - 0x%016lx\n=
", Index4, Lvl4PtEntry[Index4].Uint64));=0D
+ }=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_=
ENTRY); Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl3Pt Entry(0x%03x) - 0x%016l=
x\n", Index3, Lvl3PtEntry[Index3].Uint64));=0D
+ }=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ if (Lvl2PtEntry[Index2].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl2Pt Entry(0x%03x) - 0x%0=
16lx\n", Index2, Lvl2PtEntry[Index2].Uint64));=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Bits.PageSize =3D=3D 0) {=0D
+ Lvl1PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64=
BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.A=
ddressHi);=0D
+ for (Index1 =3D 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_P=
AGING_ENTRY); Index1++) {=0D
+ if (Lvl1PtEntry[Index1].Uint64 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, " Lvl1Pt Entry(0x%03x) =
- 0x%016lx\n", Index1, Lvl1PtEntry[Index1].Uint64));=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_VERBOSE, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D\n"));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] RootEntry DMAR root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_ROOT_ENTRY *RootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN Index2;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DMAR Context Entry Table:\n"));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "RootEntry Address - 0x%x\n", RootEntry));=0D
+=0D
+ for (Index =3D 0; Index < VTD_ROOT_ENTRY_NUMBER; Index++) {=0D
+ if ((RootEntry[Index].Uint128.Uint64Lo !=3D 0) || (RootEntry[Index].Ui=
nt128.Uint64Hi !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " RootEntry(0x%02x) B%02x - 0x%016lx %01=
6lx\n",=0D
+ Index, Index, RootEntry[Index].Uint128.Uint64Hi, RootEntry[Index].=
Uint128.Uint64Lo));=0D
+ }=0D
+ if (RootEntry[Index].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ ContextEntry =3D (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (Roo=
tEntry[Index].Bits.ContextTablePointerLo, RootEntry[Index].Bits.ContextTabl=
ePointerHi);=0D
+ for (Index2 =3D 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER; Index2++) {=0D
+ if ((ContextEntry[Index2].Uint128.Uint64Lo !=3D 0) || (ContextEntry[=
Index2].Uint128.Uint64Hi !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ContextEntry(0x%02x) D%02xF%02x - =
0x%016lx %016lx\n",=0D
+ Index2, Index2 >> 3, Index2 & 0x7, ContextEntry[Index2].Uint128.=
Uint64Hi, ContextEntry[Index2].Uint128.Uint64Lo));=0D
+ }=0D
+ if (ContextEntry[Index2].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ VtdLibDumpSecondLevelPagingEntry (Context, CallbackHandle, (VOID *) =
(UINTN) VTD_64BITS_ADDRESS (ContextEntry[Index2].Bits.SecondLevelPageTransl=
ationPointerLo, ContextEntry[Index2].Bits.SecondLevelPageTranslationPointer=
Hi), Is5LevelPaging);=0D
+ }=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR extended context entry table.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] ExtRootEntry DMAR extended root entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+VtdLibDumpDmarExtContextEntryTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_EXT_ROOT_ENTRY *ExtRootEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN Index2;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DMAR ExtContext Entry Table:\n"));=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "ExtRootEntry Address - 0x%x\n", ExtRootEntry=
));=0D
+=0D
+ for (Index =3D 0; Index < VTD_ROOT_ENTRY_NUMBER; Index++) {=0D
+ if ((ExtRootEntry[Index].Uint128.Uint64Lo !=3D 0) || (ExtRootEntry[Ind=
ex].Uint128.Uint64Hi !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ExtRootEntry(0x%02x) B%02x - 0x%016lx =
%016lx\n",=0D
+ Index, Index, ExtRootEntry[Index].Uint128.Uint64Hi, ExtRootEntry[I=
ndex].Uint128.Uint64Lo));=0D
+ }=0D
+ if (ExtRootEntry[Index].Bits.LowerPresent =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ ExtContextEntry =3D (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRE=
SS (ExtRootEntry[Index].Bits.LowerContextTablePointerLo, ExtRootEntry[Index=
].Bits.LowerContextTablePointerHi);=0D
+ for (Index2 =3D 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER/2; Index2++) {=0D
+ if ((ExtContextEntry[Index2].Uint256.Uint64_1 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_2 !=3D 0) ||=0D
+ (ExtContextEntry[Index2].Uint256.Uint64_3 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_4 !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ExtContextEntryLower(0x%02x) D%02x=
F%02x - 0x%016lx %016lx %016lx %016lx\n",=0D
+ Index2, Index2 >> 3, Index2 & 0x7, ExtContextEntry[Index2].Uint2=
56.Uint64_4, ExtContextEntry[Index2].Uint256.Uint64_3, ExtContextEntry[Inde=
x2].Uint256.Uint64_2, ExtContextEntry[Index2].Uint256.Uint64_1));=0D
+ }=0D
+ if (ExtContextEntry[Index2].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ VtdLibDumpSecondLevelPagingEntry (Context, CallbackHandle, (VOID *) =
(UINTN) VTD_64BITS_ADDRESS (ExtContextEntry[Index2].Bits.SecondLevelPageTra=
nslationPointerLo, ExtContextEntry[Index2].Bits.SecondLevelPageTranslationP=
ointerHi), Is5LevelPaging);=0D
+ }=0D
+=0D
+ if (ExtRootEntry[Index].Bits.UpperPresent =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ ExtContextEntry =3D (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRE=
SS (ExtRootEntry[Index].Bits.UpperContextTablePointerLo, ExtRootEntry[Index=
].Bits.UpperContextTablePointerHi);=0D
+ for (Index2 =3D 0; Index2 < VTD_CONTEXT_ENTRY_NUMBER/2; Index2++) {=0D
+ if ((ExtContextEntry[Index2].Uint256.Uint64_1 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_2 !=3D 0) ||=0D
+ (ExtContextEntry[Index2].Uint256.Uint64_3 !=3D 0) || (ExtContext=
Entry[Index2].Uint256.Uint64_4 !=3D 0)) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ExtContextEntryUpper(0x%02x) D%02x=
F%02x - 0x%016lx %016lx %016lx %016lx\n",=0D
+ Index2, (Index2 + 128) >> 3, (Index2 + 128) & 0x7, ExtContextEnt=
ry[Index2].Uint256.Uint64_4, ExtContextEntry[Index2].Uint256.Uint64_3, ExtC=
ontextEntry[Index2].Uint256.Uint64_2, ExtContextEntry[Index2].Uint256.Uint6=
4_1));=0D
+ }=0D
+ if (ExtContextEntry[Index2].Bits.Present =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ }=0D
+ }=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\n"));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd FRCD register.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] FrcdRegNum FRCD Register Number=0D
+ @param[in] FrcdRegTab FRCD Register Table=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdFrcdRegs (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN UINT16 FrcdRegNum,=0D
+ IN VTD_UINT128 *FrcdRegTab=0D
+ )=0D
+{=0D
+ UINT16 Index;=0D
+ VTD_FRCD_REG FrcdReg;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ for (Index =3D 0; Index < FrcdRegNum; Index++) {=0D
+ FrcdReg.Uint64[0] =3D FrcdRegTab[Index].Uint64Lo;=0D
+ FrcdReg.Uint64[1] =3D FrcdRegTab[Index].Uint64Hi;=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FRCD_REG[%d] - 0x%016lx %016lx\n", Index=
, FrcdReg.Uint64[1], FrcdReg.Uint64[0]));=0D
+ if (FrcdReg.Uint64[1] !=3D 0 || FrcdReg.Uint64[0] !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Fault Info - 0x%016lx\n", VTD_64BITS=
_ADDRESS(FrcdReg.Bits.FILo, FrcdReg.Bits.FIHi)));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Fault Bit - %d\n", FrcdReg.Bits.F));=
=0D
+ SourceId.Uint16 =3D (UINT16)FrcdReg.Bits.SID;=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Source - B%02x D%02x F%02x\n", Sourc=
eId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Type - 0x%02x\n", (FrcdReg.Bits.T1 <=
< 1) | FrcdReg.Bits.T2));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Reason - %x (Refer to VTd Spec, Appe=
ndix A)\n", FrcdReg.Bits.FR));=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsAll (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_INFO *VtdRegInfo=0D
+ )=0D
+{=0D
+ if (VtdRegInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "VTd Engine: [0x%016lx]\n", VtdRegInfo->Bas=
eAddress));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " VER_REG - 0x%08x\n", VtdRegInfo->V=
erReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " CAP_REG - 0x%016lx\n", VtdRegInfo->C=
apReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " ECAP_REG - 0x%016lx\n", VtdRegInfo->E=
capReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " GSTS_REG - 0x%08x \n", VtdRegInfo->G=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", VtdRegInfo->R=
taddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " CCMD_REG - 0x%016lx\n", VtdRegInfo->C=
cmdReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FSTS_REG - 0x%08x\n", VtdRegInfo->F=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FECTL_REG - 0x%08x\n", VtdRegInfo->F=
ectlReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FEDATA_REG - 0x%08x\n", VtdRegInfo->F=
edataReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FEADDR_REG - 0x%08x\n", VtdRegInfo->F=
eaddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FEUADDR_REG - 0x%08x\n", VtdRegInfo->F=
euaddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IQERCD_REG - 0x%016lx\n", VtdRegInfo->I=
qercdReg));=0D
+=0D
+ VtdLibDumpVtdFrcdRegs (Context, CallbackHandle, VtdRegInfo->FrcdRegNum=
, VtdRegInfo->FrcdReg);=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IVA_REG - 0x%016lx\n", VtdRegInfo->I=
vaReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IOTLB_REG - 0x%016lx\n", VtdRegInfo->I=
otlbReg));=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsThin (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_THIN_INFO *VtdRegInfo=0D
+ )=0D
+{=0D
+ if (VtdRegInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "VTd Engine: [0x%016lx]\n", VtdRegInfo->Bas=
eAddress));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " GSTS_REG - 0x%08x \n", VtdRegInfo->G=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " RTADDR_REG - 0x%016lx\n", VtdRegInfo->R=
taddrReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FSTS_REG - 0x%08x\n", VtdRegInfo->F=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FECTL_REG - 0x%08x\n", VtdRegInfo->F=
ectlReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IQERCD_REG - 0x%016lx\n", VtdRegInfo->I=
qercdReg));=0D
+=0D
+ VtdLibDumpVtdFrcdRegs (Context, CallbackHandle, VtdRegInfo->FrcdRegNum=
, VtdRegInfo->FrcdReg);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] VtdRegInfo Registers information=0D
+**/=0D
+VOID=0D
+VtdLibDumpVtdRegsQi (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTD_REGESTER_QI_INFO *VtdRegInfo=0D
+ )=0D
+{=0D
+ if (VtdRegInfo !=3D NULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "VTd Engine: [0x%016lx]\n", VtdRegInfo->Bas=
eAddress));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " FSTS_REG - 0x%08x\n", VtdRegInfo->F=
stsReg));=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " IQERCD_REG - 0x%016lx\n", VtdRegInfo->I=
qercdReg));=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd PEI pre-mem event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_2PARAM event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpPeiPreMemInfo (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_2PARAM *Event=0D
+ )=0D
+{=0D
+ UINT64 VtdBarAddress;=0D
+ UINT64 Mode;=0D
+ UINT64 Status;=0D
+=0D
+ VtdBarAddress =3D Event->Data1;=0D
+ Mode =3D Event->Data2 & 0xFF;=0D
+ Status =3D (Event->Data2>>8) & 0xFF;=0D
+=0D
+ switch (Mode) {=0D
+ case VTD_LOG_PEI_PRE_MEM_DISABLE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Disabled [0x%016lx] 0x%x=
\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_ADM:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Enable Abort DMA Mode [0=
x%016lx] 0x%x\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_TE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Enable NULL Root Entry T=
able [0x%016lx] 0x%x\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_PMR:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Enable PMR [0x%016lx] 0x=
%x\n", VtdBarAddress, Status));=0D
+ break;=0D
+ case VTD_LOG_PEI_PRE_MEM_NOT_USED:=0D
+ //=0D
+ // Not used=0D
+ //=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI (pre-memory): Unknown [0x%016lx] 0x%x\=
n", VtdBarAddress, Status));=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd Queued Invaildation event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_2PARAM event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpQueuedInvaildation (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_2PARAM *Event=0D
+ )=0D
+{=0D
+ switch (Event->Data1) {=0D
+ case VTD_LOG_QI_DISABLE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] Disable\n", Event->Data2));=0D
+ break;=0D
+ case VTD_LOG_QI_ENABLE:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] Enable\n", Event->Data2));=0D
+ break;=0D
+ case VTD_LOG_QI_ERROR_OUT_OF_RESOURCES:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] error - Out of resources\n", E=
vent->Data2));=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " [0x%016lx] error - (0x%x)\n", Event->Data=
2, Event->Data1));=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd registers event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_CONTEXT event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpRegisters (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_CONTEXT *Event=0D
+ )=0D
+{=0D
+ switch (Event->Param) {=0D
+ case VTDLOG_REGISTER_ALL:=0D
+ VtdLibDumpVtdRegsAll (Context, CallbackHandle, (VTD_REGESTER_INFO *) E=
vent->Data);=0D
+ break;=0D
+ case VTDLOG_REGISTER_THIN:=0D
+ VtdLibDumpVtdRegsThin (Context, CallbackHandle, (VTD_REGESTER_THIN_INF=
O *) Event->Data);=0D
+ break;=0D
+ case VTDLOG_REGISTER_QI:=0D
+ VtdLibDumpVtdRegsQi (Context, CallbackHandle, (VTD_REGESTER_QI_INFO *)=
Event->Data);=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, " Unknown format (%d)\n", Event->Param));=
=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd PEI Error event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_2PARAM event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpPeiError (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_2PARAM *Event=0D
+ )=0D
+{=0D
+ UINT64 Timestamp;=0D
+=0D
+ Timestamp =3D Event->Header.Timestamp;=0D
+=0D
+ switch (Event->Data1) {=0D
+ case VTD_LOG_PEI_VTD_ERROR_PPI_ALLOC:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Error - PPI alloc length [0x%01=
6lx]\n", Timestamp, Event->Data2));=0D
+ break;=0D
+ case VTD_LOG_PEI_VTD_ERROR_PPI_MAP:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Error - PPI map length [0x%016l=
x]\n", Timestamp, Event->Data2));=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Error - Unknown (%d) 0x%x\n", T=
imestamp, Event->Data1, Event->Data2));=0D
+ break;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Dump Vtd registers event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_CONTEXT event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpSetAttribute (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_CONTEXT *Event=0D
+ )=0D
+{=0D
+ VTD_PROTOCOL_SET_ATTRIBUTE * SetAttributeInfo;=0D
+=0D
+ SetAttributeInfo =3D (VTD_PROTOCOL_SET_ATTRIBUTE *) Event->Data;=0D
+=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: SetAttribute SourceId =3D 0x%04x,=
Address =3D 0x%lx, Length =3D 0x%lx, IoMmuAccess =3D 0x%lx, %r\n", =0D
+ Event->Header.Timestamp,=0D
+ SetAttributeInfo->SourceId.Uint16,=0D
+ SetAttributeInfo->DeviceAddress,=0D
+ SetAttributeInfo->Length,=0D
+ SetAttributeInfo->Status));=0D
+}=0D
+=0D
+=0D
+=0D
+/**=0D
+ Dump Vtd Root Table event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback handler=0D
+ @param[in] Event VTDLOG_EVENT_CONTEXT event=0D
+=0D
+**/=0D
+VOID=0D
+VtdLibDumpRootTable (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT_CONTEXT *Event=0D
+ )=0D
+{=0D
+ VTD_ROOT_TABLE_INFO *RootTableInfo;=0D
+=0D
+ RootTableInfo =3D (VTD_ROOT_TABLE_INFO *) Event->Data;=0D
+ if (Event->Param =3D=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Root Entry Table [0x%016lx]\n",=
Event->Header.Timestamp, RootTableInfo->BaseAddress));=0D
+ VtdLibDumpDmarContextEntryTable (Context, CallbackHandle, (VTD_ROOT_EN=
TRY *) (UINTN) RootTableInfo->TableAddress, RootTableInfo->Is5LevelPaging);=
=0D
+=0D
+ } else if (Event->Param =3D=3D 1) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Ext Root Entry Table [0x%016lx]=
\n", Event->Header.Timestamp, RootTableInfo->BaseAddress));=0D
+ VtdLibDumpDmarExtContextEntryTable (Context, CallbackHandle, (VTD_EXT_=
ROOT_ENTRY *) (UINTN) RootTableInfo->TableAddress, RootTableInfo->Is5Level=
Paging);=0D
+=0D
+ } else {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Unknown Root Table Type (%d)\n"=
, Event->Header.Timestamp, Event->Param));=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Decode log event.=0D
+=0D
+ @param[in] Context Event context=0D
+ @param[in out] PciDeviceId Callback handler=0D
+ @param[in] Event Event struct=0D
+=0D
+ @retval TRUE Decode event success=0D
+ @retval FALSE Unknown event=0D
+**/=0D
+BOOLEAN=0D
+VtdLibDecodeEvent (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LIB_STRING_CB CallbackHandle,=0D
+ IN VTDLOG_EVENT *Event=0D
+ )=0D
+{=0D
+ BOOLEAN Result;=0D
+ UINT64 Timestamp;=0D
+ UINT64 Data1;=0D
+ UINT64 Data2;=0D
+=0D
+ Result =3D TRUE;=0D
+ Timestamp =3D Event->EventHeader.Timestamp;=0D
+ Data1 =3D Event->CommenEvent.Data1;=0D
+ Data2 =3D Event->CommenEvent.Data2;=0D
+=0D
+ switch (Event->EventHeader.LogType) {=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_BASIC):=0D
+ if (Data1 & VTD_LOG_ERROR_BUFFER_FULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Info : Log Buffer Full\n", Ti=
mestamp));=0D
+ Data1 &=3D ~VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ if (Data1 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Info : 0x%x, 0x%x\n", Timesta=
mp, Data1, Data2));=0D
+ }=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PRE_MEM_DMA_PROTECT):=0D
+ VtdLibDumpPeiPreMemInfo (Context, CallbackHandle, &(Event->CommenEvent=
));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PMR_LOW_MEMORY_RANGE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PMR Low Memory Range [0x%x, 0x%=
x]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PMR_HIGH_MEMORY_RANGE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PMR High Memory Range [0x%016lx=
, 0x%016lx]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PROTECT_MEMORY_RANGE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Protected DMA Memory Range [0x%=
016lx, 0x%016lx]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_POST_MEM_ENABLE_DMA_PROTECT):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Enable DMA protection [0x%016lx=
] %r\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_POST_MEM_DISABLE_DMA_PROTECT):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Disable DMA protection [0x%016l=
x]\n", Timestamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_QUEUED_INVALIDATION):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Queued Invalidation", Timestamp=
));=0D
+ VtdLibDumpQueuedInvaildation (Context, CallbackHandle, &(Event->Commen=
Event));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_REGISTER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: Dump Registers\n", Timestamp));=
=0D
+ VtdLibDumpRegisters (Context, CallbackHandle, &(Event->ContextEvent));=
=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_VTD_ERROR):=0D
+ VtdLibDumpPeiError (Context, CallbackHandle, &(Event->CommenEvent));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PPI_ALLOC_BUFFER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PPI AllocateBuffer 0x%x, Length=
=3D 0x%x\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_PEI_PPI_MAP):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "PEI [%ld]: PPI Map 0x%x, Length =3D 0x%x\n=
", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_BASIC):=0D
+ if (Data1 & VTD_LOG_ERROR_BUFFER_FULL) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Info : Log Buffer Full\n", Ti=
mestamp));=0D
+ Data1 &=3D ~VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ if (Data1 !=3D 0) {=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Info : 0x%x, 0x%x\n", Timesta=
mp, Data1, Data2));=0D
+ }=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_DMAR_TABLE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: DMAR Table\n", Timestamp));=0D
+ VtdLibDumpAcpiDmar (Context, CallbackHandle, (EFI_ACPI_DMAR_HEADER *) =
Event->ContextEvent.Data);=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_SETUP_VTD):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Setup VTd Below/Above 4G Memory=
Limit =3D [0x%016lx, 0x%016lx]\n", Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_PCI_DEVICE):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: PCI Devices [0x%016lx]\n", Time=
stamp, Event->ContextEvent.Param));=0D
+ VtdLibDumpPciDeviceInfo (Context, CallbackHandle, (PCI_DEVICE_INFORMAT=
ION *) Event->ContextEvent.Data);=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_REGISTER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Dump Registers\n", Timestamp));=
=0D
+ VtdLibDumpRegisters (Context, CallbackHandle, &(Event->ContextEvent));=
=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_ENABLE_DMAR):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Enable DMAR [0x%016lx]\n", Time=
stamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_DISABLE_DMAR):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Disable DMAR [0x%016lx]\n", Tim=
estamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_DISABLE_PMR):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Disable PMR [0x%016lx] %r\n", T=
imestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Install IOMMU Protocol %r\n", T=
imestamp, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_QUEUED_INVALIDATION):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Queued Invalidation", Timestamp=
));=0D
+ VtdLibDumpQueuedInvaildation (Context, CallbackHandle, &(Event->Commen=
Event));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_ROOT_TABLE):=0D
+ VtdLibDumpRootTable (Context, CallbackHandle, &(Event->ContextEvent));=
=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_ALLOC_BUFFER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: AllocateBuffer 0x%x, Page =3D 0=
x%x\n", Timestamp, Data2, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_FREE_BUFFER):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: FreeBuffer 0x%x, Page =3D 0x%x\=
n", Timestamp, Data2, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_MAP):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Map 0x%x, Operation =3D 0x%x\n"=
, Timestamp, Data1, Data2));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_UNMAP):=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "DXE [%ld]: Unmap 0x%x, NumberOfBytes =3D 0=
x%x\n", Timestamp, Data2, Data1));=0D
+ break;=0D
+ case VTDLOG_LOG_TYPE (VTDLOG_DXE_IOMMU_SET_ATTRIBUTE):=0D
+ VtdLibDumpSetAttribute (Context, CallbackHandle, &(Event->ContextEvent=
));=0D
+ break;=0D
+ default:=0D
+ VTDLIB_DEBUG ((DEBUG_INFO, "## Unknown VTd Event Type=3D%d Timestamp=
=3D%ld Size=3D%d\n", Event->EventHeader.LogType, Event->EventHeader.Timesta=
mp, Event->EventHeader.DataSize));=0D
+ Result =3D FALSE;=0D
+ break;=0D
+ }=0D
+=0D
+ return Result;=0D
+}=0D
+=0D
+/**=0D
+ Flush VTd engine write buffer.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibFlushWriteBuffer (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_CAP_REG CapReg;=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+=0D
+ if (CapReg.Bits.RWBF !=3D 0) {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);=
=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_WBF) !=3D 0);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Clear Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask=0D
+**/=0D
+VOID=0D
+VtdLibClearGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ UINT32 Status;=0D
+ UINT32 Command;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Status =3D (Reg32 & 0x96FFFFFF); // Reset the one-shot bits=0D
+ Command =3D (Status & (~BitMask));=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));=0D
+=0D
+ //=0D
+ // Poll on Status bit of Global status register to become zero=0D
+ //=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & BitMask) =3D=3D BitMask);=0D
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));=0D
+}=0D
+=0D
+/**=0D
+ Set Global Command Register Bits=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] BitMask Bit mask=0D
+**/=0D
+VOID=0D
+VtdLibSetGlobalCommandRegisterBits (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINT32 BitMask=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ UINT32 Status;=0D
+ UINT32 Command;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Status =3D (Reg32 & 0x96FFFFFF); // Reset the one-shot bits=0D
+ Command =3D (Status | BitMask);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));=0D
+=0D
+ //=0D
+ // Poll on Status bit of Global status register to become not zero=0D
+ //=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & BitMask) =3D=3D 0);=0D
+ DEBUG ((DEBUG_INFO, "GSTS_REG : 0x%08x \n", Reg32));=0D
+}=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisableDmar (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+=0D
+ DEBUG ((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x]\n", VtdUnitBase=
Address));=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Disable Dmar=0D
+ //=0D
+ //=0D
+ // Set TE (Translation Enable: BIT31) of Global command register to zero=
=0D
+ //=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ //=0D
+ // Set SRTP (Set Root Table Pointer: BIT30) of Global command register i=
n order to update the root table pointerDisable VTd=0D
+ //=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP)=
;=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ DEBUG ((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));=0D
+=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, 0);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD () Disabled!<<<<<<\n"));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable PMR.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS PMR is disabled.=0D
+ @retval EFI_UNSUPPORTED PMR is not supported.=0D
+ @retval EFI_NOT_STARTED PMR was not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibDisablePmr (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_CAP_REG CapReg;=0D
+ EFI_STATUS Status;=0D
+=0D
+ CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);=0D
+ if (CapReg.Bits.PLMR =3D=3D 0 || CapReg.Bits.PHMR =3D=3D 0) {=0D
+ //=0D
+ // PMR is not supported=0D
+ //=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);=0D
+ if ((Reg32 & BIT0) !=3D 0) {=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);=0D
+ } while((Reg32 & BIT0) !=3D 0);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Pmr [0x%016lx] disabled\n", VtdUnitBaseAddress));=
=0D
+ Status =3D EFI_SUCCESS;=0D
+ } else {=0D
+ DEBUG ((DEBUG_INFO,"Pmr [0x%016lx] not enabled\n", VtdUnitBaseAddress)=
);=0D
+ Status =3D EFI_NOT_STARTED;=0D
+ }=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Disable queued invalidation interface.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+VtdLibDisableQueuedInvalidationInterface (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ QiDesc.Uint64[0] =3D QI_IWD_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress, &QiDesc, T=
RUE);=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 &=3D (~B_GMCD_REG_QIE);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. [%x] GCMD_RE=
G =3D 0x%x\n", VtdUnitBaseAddress, Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) !=3D 0);=0D
+=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, 0);=0D
+}=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Base The base address of memory to be flush=
ed.=0D
+ @param[in] Size The size of memory in bytes to be flus=
hed.=0D
+**/=0D
+VOID=0D
+VtdLibFlushPageTableMemory (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ VTD_ECAP_REG ECapReg;=0D
+=0D
+ ECapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);=0D
+ if (ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *)Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+ @param[in] ClearFaultBits Clear Error bits=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+ @retval EFI_NOT_READY Queued invalidation is not inited.=0D
+ @retval EFI_DEVICE_ERROR Detect fault, need to clear fault bits=
if ClearFaultBits is FALSE=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VtdLibSubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN VOID *Desc,=0D
+ IN BOOLEAN ClearFaultBits=0D
+ )=0D
+{=0D
+ UINTN QueueSize;=0D
+ UINTN QueueTail;=0D
+ UINTN QueueHead;=0D
+ QI_DESC *Qi128Desc;=0D
+ QI_256_DESC *Qi256Desc;=0D
+ VTD_IQA_REG IqaReg;=0D
+ VTD_IQT_REG IqtReg;=0D
+ VTD_IQH_REG IqhReg;=0D
+ UINT32 FaultReg;=0D
+ UINT64 IqercdReg;=0D
+=0D
+ if (Desc =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ if (IqaReg.Bits.IQA =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"Invalidation Queue Buffer not ready [0x%lx]\n", I=
qaReg.Uint64));=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ IqtReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQT_REG);=0D
+=0D
+ if (IqaReg.Bits.DW =3D=3D 0) {=0D
+ //=0D
+ // 128-bit descriptor=0D
+ //=0D
+ QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 8));=0D
+ Qi128Desc =3D (QI_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHIFT);=
=0D
+ QueueTail =3D (UINTN) IqtReg.Bits128Desc.QT;=0D
+ Qi128Desc +=3D QueueTail;=0D
+ CopyMem (Qi128Desc, Desc, sizeof (QI_DESC));=0D
+ VtdLibFlushPageTableMemory (VtdUnitBaseAddress, (UINTN) Qi128Desc, siz=
eof(QI_DESC));=0D
+ QueueTail =3D (QueueTail + 1) % QueueSize;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x=
%016lx]\n",=0D
+ VtdUnitBaseAddress,=0D
+ QueueTail,=0D
+ Qi128Desc->Low,=0D
+ Qi128Desc->High));=0D
+=0D
+ IqtReg.Bits128Desc.QT =3D QueueTail;=0D
+ } else {=0D
+ //=0D
+ // 256-bit descriptor=0D
+ //=0D
+ QueueSize =3D (UINTN) (1 << (IqaReg.Bits.QS + 7));=0D
+ Qi256Desc =3D (QI_256_DESC *) (UINTN) (IqaReg.Bits.IQA << VTD_PAGE_SHI=
FT);=0D
+ QueueTail =3D (UINTN) IqtReg.Bits256Desc.QT;=0D
+ Qi256Desc +=3D QueueTail;=0D
+ CopyMem (Qi256Desc, Desc, sizeof (QI_256_DESC));=0D
+ VtdLibFlushPageTableMemory (VtdUnitBaseAddress, (UINTN) Qi256Desc, siz=
eof(QI_256_DESC));=0D
+ QueueTail =3D (QueueTail + 1) % QueueSize;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "[0x%x] Submit QI Descriptor 0x%x [0x%016lx, 0x=
%016lx, 0x%016lx, 0x%016lx]\n",=0D
+ VtdUnitBaseAddress,=0D
+ QueueTail,=0D
+ Qi256Desc->Uint64[0],=0D
+ Qi256Desc->Uint64[1],=0D
+ Qi256Desc->Uint64[2],=0D
+ Qi256Desc->Uint64[3]));=0D
+=0D
+ IqtReg.Bits256Desc.QT =3D QueueTail;=0D
+ }=0D
+=0D
+ //=0D
+ // Update the HW tail register indicating the presence of new descriptor=
s.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, IqtReg.Uint64);=0D
+=0D
+ do {=0D
+ FaultReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG);=0D
+ if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {=0D
+ IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_REG);=0D
+ DEBUG((DEBUG_ERROR, "BAR [0x%016lx] Detect Queue Invalidation Fault =
[0x%08x] - IQERCD [0x%016lx]\n", VtdUnitBaseAddress, FaultReg, IqercdReg));=
=0D
+ if (ClearFaultBits) {=0D
+ FaultReg &=3D (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);=
=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, FaultReg);=0D
+ }=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ IqhReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQH_REG);=0D
+ if (IqaReg.Bits.DW =3D=3D 0) {=0D
+ QueueHead =3D (UINTN) IqhReg.Bits128Desc.QH;=0D
+ } else {=0D
+ QueueHead =3D (UINTN) IqhReg.Bits256Desc.QH;=0D
+ }=0D
+ } while (QueueTail !=3D QueueHead);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelV=
TdPeiDxeLib.inf b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/I=
ntelVTdPeiDxeLib.inf
new file mode 100644
index 000000000..0d6dff5fa
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiDx=
eLib.inf
@@ -0,0 +1,30 @@
+### @file=0D
+# Component information file for Intel VTd function library.=0D
+#=0D
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+#=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+###=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdPeiDxeLib=0D
+ FILE_GUID =3D 6cd8b1ea-152d-4cc9-b9b1-f5c692ba63da=
=0D
+ VERSION_STRING =3D 1.0=0D
+ MODULE_TYPE =3D BASE=0D
+ LIBRARY_CLASS =3D IntelVTdPeiDxeLib=0D
+=0D
+[LibraryClasses]=0D
+ BaseLib=0D
+ PrintLib=0D
+ IoLib=0D
+ CacheMaintenanceLib=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[Sources]=0D
+ IntelVTdPeiDxeLib.c=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelV=
TdPeiDxeLibExt.inf b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLi=
b/IntelVTdPeiDxeLibExt.inf
new file mode 100644
index 000000000..9a2b28e12
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib/IntelVTdPeiDx=
eLibExt.inf
@@ -0,0 +1,34 @@
+### @file=0D
+# Component information file for Intel VTd function library.=0D
+#=0D
+# Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>=0D
+#=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+###=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdPeiDxeLib=0D
+ FILE_GUID =3D 6fd8b3aa-852d-6ccA-b9b2-f5c692ba63ca=
=0D
+ VERSION_STRING =3D 1.0=0D
+ MODULE_TYPE =3D BASE=0D
+ LIBRARY_CLASS =3D IntelVTdPeiDxeLib=0D
+=0D
+[LibraryClasses]=0D
+ BaseLib=0D
+ PrintLib=0D
+ IoLib=0D
+ CacheMaintenanceLib=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[Sources]=0D
+ IntelVTdPeiDxeLib.c=0D
+=0D
+[BuildOptions]=0D
+ *_*_X64_CC_FLAGS =3D -DEXT_CALLBACK=0D
+=0D
--=20
2.26.2.windows.1
[PATCH v3 2/2] OvmfPkg/ResetVector: Define SNP metadata for kernel hashes
Dov Murik
In order to allow the VMM (such as QEMU) to add a page with hashes of
kernel/initrd/cmdline for measured direct boot on SNP, add it explicitly
to the SNP metadata list report to the VMM.
In such case, VMM should fill the page with the hashes content, or
explicitly update it as a zero page (if kernel hashes are not used).
Note that for SNP, the launch secret part of the page (lower 3KB) are
not relevant and will remain zero. The last 1KB is used for the hashes.
This should have no effect on OvmfPkgX64 targets (which don't define
PcdSevLaunchSecretBase).
Signed-off-by: Dov Murik <dovmurik@...>
---
OvmfPkg/ResetVector/ResetVector.nasmb | 11 ++++++++++-
OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm | 11 +++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/Re=
setVector.nasmb
index 94fbb0a87b37..5832aaa8abf7 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -64,6 +64,15 @@
%define SEV_SNP_SECRETS_SIZE (FixedPcdGet32 (PcdOvmfSnpSecretsSiz=
e))=0D
%define CPUID_BASE (FixedPcdGet32 (PcdOvmfCpuidBase))=0D
%define CPUID_SIZE (FixedPcdGet32 (PcdOvmfCpuidSize))=0D
+%if (FixedPcdGet32 (PcdSevLaunchSecretBase) > 0)=0D
+ ; There's a reserved page for SEV secrets and hashes; the VMM will fill =
and=0D
+ ; validate the page, or mark it as a zero page.=0D
+ %define SEV_SNP_KERNEL_HASHES_BASE (FixedPcdGet32 (PcdSevLaunchSecret=
Base))=0D
+ %define SEV_SNP_KERNEL_HASHES_SIZE (FixedPcdGet32 (PcdSevLaunchSecret=
Size) + FixedPcdGet32 (PcdQemuHashTableSize))=0D
+%else=0D
+ %define SEV_SNP_KERNEL_HASHES_BASE 0=0D
+ %define SEV_SNP_KERNEL_HASHES_SIZE 0=0D
+%endif=0D
%define SNP_SEC_MEM_BASE_DESC_1 (FixedPcdGet32 (PcdOvmfSecPageTables=
Base))=0D
%define SNP_SEC_MEM_SIZE_DESC_1 (FixedPcdGet32 (PcdOvmfSecGhcbBase) =
- SNP_SEC_MEM_BASE_DESC_1)=0D
;=0D
@@ -75,7 +84,7 @@
;=0D
%define SNP_SEC_MEM_BASE_DESC_2 (GHCB_BASE + 0x1000)=0D
%define SNP_SEC_MEM_SIZE_DESC_2 (SEV_SNP_SECRETS_BASE - SNP_SEC_MEM_=
BASE_DESC_2)=0D
-%define SNP_SEC_MEM_BASE_DESC_3 (CPUID_BASE + CPUID_SIZE)=0D
+%define SNP_SEC_MEM_BASE_DESC_3 (CPUID_BASE + CPUID_SIZE + SEV_SNP_K=
ERNEL_HASHES_SIZE)=0D
%define SNP_SEC_MEM_SIZE_DESC_3 (FixedPcdGet32 (PcdOvmfPeiMemFvBase)=
- SNP_SEC_MEM_BASE_DESC_3)=0D
=0D
%ifdef ARCH_X64=0D
diff --git a/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm b/OvmfPkg/ResetVec=
tor/X64/OvmfSevMetadata.asm
index d03fc6d45175..8aa77d870123 100644
--- a/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm
+++ b/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm
@@ -26,6 +26,8 @@ BITS 64
;=0D
%define OVMF_SECTION_TYPE_CPUID 0x3=0D
=0D
+; Kernel hashes section for measured direct boot=0D
+%define OVMF_SECTION_TYPE_KERNEL_HASHES 0x10=0D
=0D
ALIGN 16=0D
=0D
@@ -65,6 +67,15 @@ CpuidSec:
DD CPUID_SIZE=0D
DD OVMF_SECTION_TYPE_CPUID=0D
=0D
+%if (SEV_SNP_KERNEL_HASHES_BASE > 0)=0D
+; Kernel hashes for measured direct boot, or zero page if=0D
+; there are no kernel hashes / SEV secrets=0D
+SevSnpKernelHashes:=0D
+ DD SEV_SNP_KERNEL_HASHES_BASE=0D
+ DD SEV_SNP_KERNEL_HASHES_SIZE=0D
+ DD OVMF_SECTION_TYPE_KERNEL_HASHES=0D
+%endif=0D
+=0D
; Region need to be pre-validated by the hypervisor=0D
PreValidate3:=0D
DD SNP_SEC_MEM_BASE_DESC_3=0D
--=20
2.25.1
kernel/initrd/cmdline for measured direct boot on SNP, add it explicitly
to the SNP metadata list report to the VMM.
In such case, VMM should fill the page with the hashes content, or
explicitly update it as a zero page (if kernel hashes are not used).
Note that for SNP, the launch secret part of the page (lower 3KB) are
not relevant and will remain zero. The last 1KB is used for the hashes.
This should have no effect on OvmfPkgX64 targets (which don't define
PcdSevLaunchSecretBase).
Signed-off-by: Dov Murik <dovmurik@...>
---
OvmfPkg/ResetVector/ResetVector.nasmb | 11 ++++++++++-
OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm | 11 +++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/ResetVector/ResetVector.nasmb b/OvmfPkg/ResetVector/Re=
setVector.nasmb
index 94fbb0a87b37..5832aaa8abf7 100644
--- a/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -64,6 +64,15 @@
%define SEV_SNP_SECRETS_SIZE (FixedPcdGet32 (PcdOvmfSnpSecretsSiz=
e))=0D
%define CPUID_BASE (FixedPcdGet32 (PcdOvmfCpuidBase))=0D
%define CPUID_SIZE (FixedPcdGet32 (PcdOvmfCpuidSize))=0D
+%if (FixedPcdGet32 (PcdSevLaunchSecretBase) > 0)=0D
+ ; There's a reserved page for SEV secrets and hashes; the VMM will fill =
and=0D
+ ; validate the page, or mark it as a zero page.=0D
+ %define SEV_SNP_KERNEL_HASHES_BASE (FixedPcdGet32 (PcdSevLaunchSecret=
Base))=0D
+ %define SEV_SNP_KERNEL_HASHES_SIZE (FixedPcdGet32 (PcdSevLaunchSecret=
Size) + FixedPcdGet32 (PcdQemuHashTableSize))=0D
+%else=0D
+ %define SEV_SNP_KERNEL_HASHES_BASE 0=0D
+ %define SEV_SNP_KERNEL_HASHES_SIZE 0=0D
+%endif=0D
%define SNP_SEC_MEM_BASE_DESC_1 (FixedPcdGet32 (PcdOvmfSecPageTables=
Base))=0D
%define SNP_SEC_MEM_SIZE_DESC_1 (FixedPcdGet32 (PcdOvmfSecGhcbBase) =
- SNP_SEC_MEM_BASE_DESC_1)=0D
;=0D
@@ -75,7 +84,7 @@
;=0D
%define SNP_SEC_MEM_BASE_DESC_2 (GHCB_BASE + 0x1000)=0D
%define SNP_SEC_MEM_SIZE_DESC_2 (SEV_SNP_SECRETS_BASE - SNP_SEC_MEM_=
BASE_DESC_2)=0D
-%define SNP_SEC_MEM_BASE_DESC_3 (CPUID_BASE + CPUID_SIZE)=0D
+%define SNP_SEC_MEM_BASE_DESC_3 (CPUID_BASE + CPUID_SIZE + SEV_SNP_K=
ERNEL_HASHES_SIZE)=0D
%define SNP_SEC_MEM_SIZE_DESC_3 (FixedPcdGet32 (PcdOvmfPeiMemFvBase)=
- SNP_SEC_MEM_BASE_DESC_3)=0D
=0D
%ifdef ARCH_X64=0D
diff --git a/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm b/OvmfPkg/ResetVec=
tor/X64/OvmfSevMetadata.asm
index d03fc6d45175..8aa77d870123 100644
--- a/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm
+++ b/OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm
@@ -26,6 +26,8 @@ BITS 64
;=0D
%define OVMF_SECTION_TYPE_CPUID 0x3=0D
=0D
+; Kernel hashes section for measured direct boot=0D
+%define OVMF_SECTION_TYPE_KERNEL_HASHES 0x10=0D
=0D
ALIGN 16=0D
=0D
@@ -65,6 +67,15 @@ CpuidSec:
DD CPUID_SIZE=0D
DD OVMF_SECTION_TYPE_CPUID=0D
=0D
+%if (SEV_SNP_KERNEL_HASHES_BASE > 0)=0D
+; Kernel hashes for measured direct boot, or zero page if=0D
+; there are no kernel hashes / SEV secrets=0D
+SevSnpKernelHashes:=0D
+ DD SEV_SNP_KERNEL_HASHES_BASE=0D
+ DD SEV_SNP_KERNEL_HASHES_SIZE=0D
+ DD OVMF_SECTION_TYPE_KERNEL_HASHES=0D
+%endif=0D
+=0D
; Region need to be pre-validated by the hypervisor=0D
PreValidate3:=0D
DD SNP_SEC_MEM_BASE_DESC_3=0D
--=20
2.25.1
[PATCH v3 1/2] OvmfPkg/AmdSev: Reorder MEMFD pages to match the order in OvmfPkgX64.fdf
Dov Murik
Resize the MEMFD section of AmdSevX64.fdf and reorder its pages so that
it matches the same size and order used in OvmfPkgX64.fdf.
After this change, this is the difference in the MEMFD of the two
targets:
$ diff -u \
<(sed -ne '/FD.MEMFD/,/FV.SECFV/p' OvmfPkg/OvmfPkgX64.fdf) \
<(sed -ne '/FD.MEMFD/,/FV.SECFV/p' OvmfPkg/AmdSev/AmdSevX64.fdf)
--- /dev/fd/63 2023-02-16 07:06:15.365308683 +0000
+++ /dev/fd/62 2023-02-16 07:06:15.365308683 +0000
@@ -32,6 +32,12 @@
0x00E000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.Pcd=
OvmfCpuidSize
+0x00F000|0x000C00
+gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGu=
id.PcdSevLaunchSecretSize
+
+0x00FC00|0x000400
+gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid=
.PcdQemuHashTableSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecPeiTempRamSize
Signed-off-by: Dov Murik <dovmurik@...>
---
OvmfPkg/AmdSev/AmdSevX64.fdf | 27 ++++++++++----------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index 5fb3b5d27632..54ba9ecf5149 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -36,10 +36,10 @@ FV =3D SECFV
=0D
[FD.MEMFD]=0D
BaseAddress =3D $(MEMFD_BASE_ADDRESS)=0D
-Size =3D 0xD00000=0D
+Size =3D 0xE00000=0D
ErasePolarity =3D 1=0D
BlockSize =3D 0x10000=0D
-NumBlocks =3D 0xD0=0D
+NumBlocks =3D 0xE0=0D
=0D
0x000000|0x006000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecPageTablesSize=0D
@@ -59,21 +59,21 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|gUefiOvmf=
PkgTokenSpaceGuid.PcdOvmf
0x00B000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.=
PcdOvmfWorkAreaSize=0D
=0D
-0x00C000|0x000C00=0D
-gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGu=
id.PcdSevLaunchSecretSize=0D
-=0D
-0x00CC00|0x000400=0D
-gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid=
.PcdQemuHashTableSize=0D
-=0D
-0x00D000|0x001000=0D
+0x00C000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecGhcbBackupSize=0D
=0D
-0x00E000|0x001000=0D
+0x00D000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGui=
d.PcdOvmfSnpSecretsSize=0D
=0D
-0x00F000|0x001000=0D
+0x00E000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.Pcd=
OvmfCpuidSize=0D
=0D
+0x00F000|0x000C00=0D
+gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGu=
id.PcdSevLaunchSecretSize=0D
+=0D
+0x00FC00|0x000400=0D
+gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid=
.PcdQemuHashTableSize=0D
+=0D
0x010000|0x010000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecPeiTempRamSize=0D
=0D
@@ -81,12 +81,13 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUe=
fiOvmfPkgTokenSpaceGuid.P
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.=
PcdOvmfPeiMemFvSize=0D
FV =3D PEIFV=0D
=0D
-0x100000|0xC00000=0D
+0x100000|0xD00000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.=
PcdOvmfDxeMemFvSize=0D
FV =3D DXEFV=0D
=0D
##########################################################################=
################=0D
-# Set the SEV-ES specific work area PCDs=0D
+# Set the SEV-ES specific work area PCDs (used for all forms of SEV since =
the=0D
+# the SEV STATUS MSR is now saved in the work area)=0D
#=0D
SET gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase =3D $(MEMFD_BASE_ADDRES=
S) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase + gUefiOvmfPkgTokenSpa=
ceGuid.PcdOvmfConfidentialComputingWorkAreaHeader=0D
SET gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize =3D gUefiOvmfPkgTokenSp=
aceGuid.PcdOvmfWorkAreaSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfConfidentia=
lComputingWorkAreaHeader=0D
--=20
2.25.1
it matches the same size and order used in OvmfPkgX64.fdf.
After this change, this is the difference in the MEMFD of the two
targets:
$ diff -u \
<(sed -ne '/FD.MEMFD/,/FV.SECFV/p' OvmfPkg/OvmfPkgX64.fdf) \
<(sed -ne '/FD.MEMFD/,/FV.SECFV/p' OvmfPkg/AmdSev/AmdSevX64.fdf)
--- /dev/fd/63 2023-02-16 07:06:15.365308683 +0000
+++ /dev/fd/62 2023-02-16 07:06:15.365308683 +0000
@@ -32,6 +32,12 @@
0x00E000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.Pcd=
OvmfCpuidSize
+0x00F000|0x000C00
+gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGu=
id.PcdSevLaunchSecretSize
+
+0x00FC00|0x000400
+gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid=
.PcdQemuHashTableSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecPeiTempRamSize
Signed-off-by: Dov Murik <dovmurik@...>
---
OvmfPkg/AmdSev/AmdSevX64.fdf | 27 ++++++++++----------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index 5fb3b5d27632..54ba9ecf5149 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -36,10 +36,10 @@ FV =3D SECFV
=0D
[FD.MEMFD]=0D
BaseAddress =3D $(MEMFD_BASE_ADDRESS)=0D
-Size =3D 0xD00000=0D
+Size =3D 0xE00000=0D
ErasePolarity =3D 1=0D
BlockSize =3D 0x10000=0D
-NumBlocks =3D 0xD0=0D
+NumBlocks =3D 0xE0=0D
=0D
0x000000|0x006000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecPageTablesSize=0D
@@ -59,21 +59,21 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|gUefiOvmf=
PkgTokenSpaceGuid.PcdOvmf
0x00B000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.=
PcdOvmfWorkAreaSize=0D
=0D
-0x00C000|0x000C00=0D
-gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGu=
id.PcdSevLaunchSecretSize=0D
-=0D
-0x00CC00|0x000400=0D
-gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid=
.PcdQemuHashTableSize=0D
-=0D
-0x00D000|0x001000=0D
+0x00C000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecGhcbBackupSize=0D
=0D
-0x00E000|0x001000=0D
+0x00D000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSnpSecretsBase|gUefiOvmfPkgTokenSpaceGui=
d.PcdOvmfSnpSecretsSize=0D
=0D
-0x00F000|0x001000=0D
+0x00E000|0x001000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.Pcd=
OvmfCpuidSize=0D
=0D
+0x00F000|0x000C00=0D
+gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGu=
id.PcdSevLaunchSecretSize=0D
+=0D
+0x00FC00|0x000400=0D
+gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid=
.PcdQemuHashTableSize=0D
+=0D
0x010000|0x010000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpace=
Guid.PcdOvmfSecPeiTempRamSize=0D
=0D
@@ -81,12 +81,13 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUe=
fiOvmfPkgTokenSpaceGuid.P
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.=
PcdOvmfPeiMemFvSize=0D
FV =3D PEIFV=0D
=0D
-0x100000|0xC00000=0D
+0x100000|0xD00000=0D
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.=
PcdOvmfDxeMemFvSize=0D
FV =3D DXEFV=0D
=0D
##########################################################################=
################=0D
-# Set the SEV-ES specific work area PCDs=0D
+# Set the SEV-ES specific work area PCDs (used for all forms of SEV since =
the=0D
+# the SEV STATUS MSR is now saved in the work area)=0D
#=0D
SET gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase =3D $(MEMFD_BASE_ADDRES=
S) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase + gUefiOvmfPkgTokenSpa=
ceGuid.PcdOvmfConfidentialComputingWorkAreaHeader=0D
SET gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize =3D gUefiOvmfPkgTokenSp=
aceGuid.PcdOvmfWorkAreaSize - gUefiOvmfPkgTokenSpaceGuid.PcdOvmfConfidentia=
lComputingWorkAreaHeader=0D
--=20
2.25.1
[PATCH v3 0/2] OvmfPkg: Enable measured direct boot on AMD SEV-SNP
Dov Murik
AMD SEV and SEV-ES support measured direct boot with
kernel/initrd/cmdline hashes injected by QEMU and verified by OVMF
during boot.
To enable the same approach for AMD SEV-SNP, we declare the kernel
hashes page in the SNP metadata list as a new region type. When QEMU
encounters that region in the list, it will insert the hashes of
kernel/initrd/cmdline and encrypt the page (or, if the user turned off
kernel hashes, it will validate the page as a zero page).
The first patch rearranges the pages in AmdSevX64's MEMFD so they are in
the same order both as in the main target (OvmfPkgX64), with the
exception of the SEV Launch Secret page which isn't defined in
OvmfPkgX64.
The second patch modifies the SNP metadata structure such that on
AmdSev target the SEV Launch Secret page is explicitly defined in SNP
metadata list, and therefore it is not included in the ranges that are
pre-validated (zero pages) by the VMM; instead the VMM will insert
content into this page (the hashes table), or mark it explicitly as a
zero page if no hashes are added.
This series is available at:
https://github.com/confidential-containers-demo/edk2/tree/snp-kernel-hashes-v3
A corresponding QEMU RFC series will be published soon in qemu-devel, or
use this tree:
https://github.com/confidential-containers-demo/qemu/tree/snp-kernel-hashes-v3
Cc: Ard Biesheuvel <ardb+tianocore@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jordan Justen <jordan.l.justen@...>
Cc: Gerd Hoffmann <kraxel@...>
Cc: Erdem Aktas <erdemaktas@...>
Cc: James Bottomley <jejb@...>
Cc: Min Xu <min.m.xu@...>
Cc: Tom Lendacky <thomas.lendacky@...>
Cc: Michael Roth <michael.roth@...>
Cc: Ashish Kalra <ashish.kalra@...>
Cc: Mario Smarduch <mario.smarduch@...>
Cc: Tobin Feldman-Fitzthum <tobin@...>
---
v3 changes:
* Define the kernel hashes page in the SNP metadata table (thanks Tom)
v2: https://edk2.groups.io/g/devel/message/100362
v2 changes:
* Rebased on master
* Updated AmdSev MEMFD size to match OvmfX64
v1: https://edk2.groups.io/g/devel/message/88137
Dov Murik (2):
OvmfPkg/AmdSev: Reorder MEMFD pages to match the order in
OvmfPkgX64.fdf
OvmfPkg/ResetVector: Define SNP metadata for kernel hashes
OvmfPkg/AmdSev/AmdSevX64.fdf | 27 ++++++++++----------
OvmfPkg/ResetVector/ResetVector.nasmb | 11 +++++++-
OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm | 11 ++++++++
3 files changed, 35 insertions(+), 14 deletions(-)
--
2.25.1
kernel/initrd/cmdline hashes injected by QEMU and verified by OVMF
during boot.
To enable the same approach for AMD SEV-SNP, we declare the kernel
hashes page in the SNP metadata list as a new region type. When QEMU
encounters that region in the list, it will insert the hashes of
kernel/initrd/cmdline and encrypt the page (or, if the user turned off
kernel hashes, it will validate the page as a zero page).
The first patch rearranges the pages in AmdSevX64's MEMFD so they are in
the same order both as in the main target (OvmfPkgX64), with the
exception of the SEV Launch Secret page which isn't defined in
OvmfPkgX64.
The second patch modifies the SNP metadata structure such that on
AmdSev target the SEV Launch Secret page is explicitly defined in SNP
metadata list, and therefore it is not included in the ranges that are
pre-validated (zero pages) by the VMM; instead the VMM will insert
content into this page (the hashes table), or mark it explicitly as a
zero page if no hashes are added.
This series is available at:
https://github.com/confidential-containers-demo/edk2/tree/snp-kernel-hashes-v3
A corresponding QEMU RFC series will be published soon in qemu-devel, or
use this tree:
https://github.com/confidential-containers-demo/qemu/tree/snp-kernel-hashes-v3
Cc: Ard Biesheuvel <ardb+tianocore@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jordan Justen <jordan.l.justen@...>
Cc: Gerd Hoffmann <kraxel@...>
Cc: Erdem Aktas <erdemaktas@...>
Cc: James Bottomley <jejb@...>
Cc: Min Xu <min.m.xu@...>
Cc: Tom Lendacky <thomas.lendacky@...>
Cc: Michael Roth <michael.roth@...>
Cc: Ashish Kalra <ashish.kalra@...>
Cc: Mario Smarduch <mario.smarduch@...>
Cc: Tobin Feldman-Fitzthum <tobin@...>
---
v3 changes:
* Define the kernel hashes page in the SNP metadata table (thanks Tom)
v2: https://edk2.groups.io/g/devel/message/100362
v2 changes:
* Rebased on master
* Updated AmdSev MEMFD size to match OvmfX64
v1: https://edk2.groups.io/g/devel/message/88137
Dov Murik (2):
OvmfPkg/AmdSev: Reorder MEMFD pages to match the order in
OvmfPkgX64.fdf
OvmfPkg/ResetVector: Define SNP metadata for kernel hashes
OvmfPkg/AmdSev/AmdSevX64.fdf | 27 ++++++++++----------
OvmfPkg/ResetVector/ResetVector.nasmb | 11 +++++++-
OvmfPkg/ResetVector/X64/OvmfSevMetadata.asm | 11 ++++++++
3 files changed, 35 insertions(+), 14 deletions(-)
--
2.25.1
Re: [edk2-staging][PATCH 1/3] RedfishClientPkg: RedfishFeatureUtilityLib
Chang, Abner
[AMD Official Use Only - General]
Hi Nickle,
One comment to the new added function.
Abner
toggle quoted message
Show quoted text
Hi Nickle,
One comment to the new added function.
Abner
-----Original Message-----[Chang, Abner]
From: Nickle Wang <nicklew@...>
Sent: Wednesday, March 1, 2023 10:09 PM
To: devel@edk2.groups.io
Cc: Chang, Abner <Abner.Chang@...>; Igor Kulchytskyy
<igork@...>; Nick Ramirez <nramirez@...>
Subject: [edk2-staging][PATCH 1/3] RedfishClientPkg:
RedfishFeatureUtilityLib
Caution: This message originated from an External Source. Use proper
caution when opening attachments, clicking links, or responding.
- Add new interface GetPendingSettings() to check and see if
"Redfish.Settings" is in the JSON data or not. If "Redfish.Settings"
is found, return the URI and the context to Redfish pending settings.
- Fix missing FreePool() and uncrustify issues.
Signed-off-by: Nickle Wang <nicklew@...>
Cc: Abner Chang <abner.chang@...>
Cc: Igor Kulchytskyy <igork@...>
Cc: Nick Ramirez <nramirez@...>
---
.../Library/RedfishFeatureUtilityLib.h | 260 ++--
.../RedfishFeatureUtilityLib.c | 1118 +++++++++--------
2 files changed, 770 insertions(+), 608 deletions(-)
diff --git a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
index 1325976d8c..857f8c6ce6 100644
--- a/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
+++ b/RedfishClientPkg/Include/Library/RedfishFeatureUtilityLib.h
@@ -2,6 +2,7 @@
This file defines the Redfish Feature Utility Library interface.
(C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -18,16 +19,16 @@
// Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
//
typedef struct {
- UINTN Index;
- EFI_STRING ConfigureLang;
+ UINTN Index;
+ EFI_STRING ConfigureLang;
} REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG;
//
// Definition of REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
//
typedef struct {
- UINTN Count;
- REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *List;
+ UINTN Count;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *List;
} REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST;
/**
@@ -44,9 +45,9 @@ typedef struct {
**/
EFI_STATUS
GetResourceByUri (
- IN REDFISH_SERVICE *Service,
- IN EFI_STRING ResourceUri,
- OUT REDFISH_RESPONSE *Response
+ IN REDFISH_SERVICE *Service,
+ IN EFI_STRING ResourceUri,
+ OUT REDFISH_RESPONSE *Response
);
/**
@@ -66,9 +67,9 @@ GetResourceByUri (
**/
EFI_STATUS
IsRedpathArray (
- IN EFI_STRING ConfigureLang,
- OUT EFI_STRING *ArraySignatureOpen,
- OUT EFI_STRING *ArraySignatureClose
+ IN EFI_STRING ConfigureLang,
+ OUT EFI_STRING *ArraySignatureOpen,
+ OUT EFI_STRING *ArraySignatureClose
);
/**
@@ -106,8 +107,8 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang (
**/
EFI_STATUS
CopyConfiglanguageList (
- IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
- OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
);
/**
@@ -121,7 +122,7 @@ CopyConfiglanguageList (
**/
UINTN
GetNumberOfRedpathNodes (
- IN EFI_STRING NodeString
+ IN EFI_STRING NodeString
);
/**
@@ -138,9 +139,9 @@ GetNumberOfRedpathNodes (
**/
EFI_STRING
GetRedpathNodeByIndex (
- IN EFI_STRING NodeString,
- IN UINTN Index,
- OUT EFI_STRING *EndOfNodePtr OPTIONAL
+ IN EFI_STRING NodeString,
+ IN UINTN Index,
+ OUT EFI_STRING *EndOfNodePtr OPTIONAL
);
/**
@@ -159,9 +160,9 @@ GetRedpathNodeByIndex (
**/
EFI_STATUS
GetArrayIndexFromArrayTypeConfigureLang (
- IN CHAR16 *ConfigureLang,
- OUT CHAR16 **UnifiedConfigureLang,
- OUT UINTN *Index
+ IN CHAR16 *ConfigureLang,
+ OUT CHAR16 **UnifiedConfigureLang,
+ OUT UINTN *Index
);
/**
@@ -175,7 +176,7 @@ GetArrayIndexFromArrayTypeConfigureLang (
**/
UINTN
ConfiglanguageGetInstanceIndex (
- IN EFI_STRING ConfigureLang
+ IN EFI_STRING ConfigureLang
);
/**
@@ -191,7 +192,7 @@ ConfiglanguageGetInstanceIndex (
**/
EFI_STATUS
DestroyConfiglanguageList (
- IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
);
/**
@@ -211,9 +212,9 @@ DestroyConfiglanguageList (
**/
EFI_STATUS
SetResourceConfigLangMemberInstance (
- IN EFI_STRING *DestConfigLang,
- IN UINTN MaxtLengthConfigLang,
- IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance
+ IN EFI_STRING *DestConfigLang,
+ IN UINTN MaxtLengthConfigLang,
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance
);
/**
@@ -229,8 +230,8 @@ SetResourceConfigLangMemberInstance (
**/
EFI_STATUS
GetArraykeyFromUri (
- IN CHAR8 *Uri,
- OUT CHAR8 **ArrayKey
+ IN CHAR8 *Uri,
+ OUT CHAR8 **ArrayKey
);
/**
@@ -248,10 +249,10 @@ GetArraykeyFromUri (
**/
EFI_STATUS
ApplyFeatureSettingsStringType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN CHAR8 *FeatureValue
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN CHAR8 *FeatureValue
);
/**
@@ -269,10 +270,10 @@ ApplyFeatureSettingsStringType (
**/
EFI_STATUS
ApplyFeatureSettingsNumericType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN INTN FeatureValue
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN INTN FeatureValue
);
/**
@@ -290,10 +291,10 @@ ApplyFeatureSettingsNumericType (
**/
EFI_STATUS
ApplyFeatureSettingsBooleanType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN BOOLEAN FeatureValue
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN BOOLEAN FeatureValue
);
/**
@@ -312,11 +313,11 @@ ApplyFeatureSettingsBooleanType (
**/
EFI_STATUS
ApplyFeatureSettingsVagueType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
- IN UINT32 NumberOfVagueValues
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
+ IN UINT32 NumberOfVagueValues
);
/**
@@ -355,9 +356,9 @@ ApplyFeatureSettingsStringArrayType (
**/
EFI_STATUS
ApplyFeatureSettingsNumericArrayType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
IN RedfishCS_int64_Array *ArrayHead
);
@@ -398,11 +399,11 @@ ApplyFeatureSettingsBooleanArrayType (
**/
EFI_STATUS
CreatePayloadToPostResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT EFI_STRING *Location,
- OUT CHAR8 **Etag
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT EFI_STRING *Location,
+ OUT CHAR8 **Etag
);
/**
@@ -420,10 +421,10 @@ CreatePayloadToPostResource (
**/
EFI_STATUS
CreatePayloadToPatchResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Etag
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT CHAR8 **Etag
);
/**
@@ -456,8 +457,8 @@ RedfisSetRedfishUri (
**/
EFI_STRING
GetPropertyFromConfigureLang (
- IN EFI_STRING ResourceUri,
- IN EFI_STRING ConfigureLang
+ IN EFI_STRING ResourceUri,
+ IN EFI_STRING ConfigureLang
);
/**
@@ -475,10 +476,10 @@ GetPropertyFromConfigureLang (
**/
CHAR8 *
GetPropertyStringValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
);
/**
@@ -496,10 +497,10 @@ GetPropertyStringValue (
**/
INT64 *
GetPropertyNumericValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
);
/**
@@ -516,10 +517,10 @@ GetPropertyNumericValue (
**/
BOOLEAN *
GetPropertyBooleanValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
);
/**
@@ -535,8 +536,8 @@ GetPropertyBooleanValue (
**/
BOOLEAN
PropertyChecker (
- IN VOID *PropertyBuffer,
- IN BOOLEAN ProvisionMode
+ IN VOID *PropertyBuffer,
+ IN BOOLEAN ProvisionMode
);
/**
@@ -583,7 +584,7 @@ GetEtagWithUri (
**/
EFI_STRING
GetOdataId (
- IN REDFISH_PAYLOAD *Payload
+ IN REDFISH_PAYLOAD *Payload
);
/**
@@ -599,8 +600,8 @@ GetOdataId (
**/
EFI_STRING
GetConfigureLang (
- IN CHAR8 *Uri,
- IN CHAR8 *PropertyName OPTIONAL
+ IN CHAR8 *Uri,
+ IN CHAR8 *PropertyName OPTIONAL
);
/**
@@ -615,7 +616,7 @@ GetConfigureLang (
**/
EFI_STRING
RedfishGetUri (
- IN EFI_STRING ConfigLang
+ IN EFI_STRING ConfigLang
);
/**
@@ -630,7 +631,7 @@ RedfishGetUri (
**/
EFI_STRING
RedfishGetConfigLanguage (
- IN EFI_STRING Uri
+ IN EFI_STRING Uri
);
/**
@@ -645,7 +646,7 @@ RedfishGetConfigLanguage (
**/
CHAR8 *
StrUnicodeToAscii (
- IN EFI_STRING UnicodeStr
+ IN EFI_STRING UnicodeStr
);
/**
@@ -677,9 +678,9 @@ StrAsciiToUnicode (
**/
BOOLEAN
CheckEtag (
- IN EFI_STRING Uri,
- IN CHAR8 *EtagInHeader,
- IN CHAR8 *EtagInJson
+ IN EFI_STRING Uri,
+ IN CHAR8 *EtagInHeader,
+ IN CHAR8 *EtagInJson
);
/**
@@ -697,11 +698,11 @@ CheckEtag (
**/
CHAR8 **
GetPropertyStringArrayValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINTN *ArraySize
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
);
/**
@@ -719,11 +720,11 @@ GetPropertyStringArrayValue (
**/
INT64 *
GetPropertyNumericArrayValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINTN *ArraySize
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
);
/**
@@ -741,11 +742,11 @@ GetPropertyNumericArrayValue (
**/
BOOLEAN *
GetPropertyBooleanArrayValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINTN *ArraySize
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
);
/**
@@ -764,11 +765,11 @@ GetPropertyBooleanArrayValue (
**/
RedfishCS_EmptyProp_KeyValue *
GetPropertyVagueValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINT32 *NumberOfValues
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINT32 *NumberOfValues
);
/**
@@ -780,7 +781,7 @@ GetPropertyVagueValue (
**/
VOID
FreeEmptyPropKeyValueList (
- RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
);
/**
@@ -798,7 +799,7 @@ BOOLEAN
MatchPropertyWithJsonContext (
IN EFI_STRING Property,
IN CHAR8 *Json
-);
+ );
/**
@@ -814,7 +815,7 @@ MatchPropertyWithJsonContext (
**/
EFI_STATUS
AddRedfishCharArray (
- IN OUT RedfishCS_char_Array **Head,
+ IN OUT RedfishCS_char_Array **Head,
IN CHAR8 **StringArray,
IN UINTN ArraySize
);
@@ -833,9 +834,9 @@ AddRedfishCharArray (
**/
EFI_STATUS
AddRedfishNumericArray (
- IN OUT RedfishCS_int64_Array **Head,
- IN INT64 *NumericArray,
- IN UINTN ArraySize
+ IN OUT RedfishCS_int64_Array **Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
);
/**
@@ -856,6 +857,7 @@ AddRedfishBooleanArray (
IN BOOLEAN *BooleanArray,
IN UINTN ArraySize
);
+
/**
Check and see if value in Redfish string array are all the same as the one
@@ -872,9 +874,9 @@ AddRedfishBooleanArray (
**/
BOOLEAN
CompareRedfishStringArrayValues (
- IN RedfishCS_char_Array *Head,
- IN CHAR8 **StringArray,
- IN UINTN ArraySize
+ IN RedfishCS_char_Array *Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
);
/**
@@ -893,9 +895,9 @@ CompareRedfishStringArrayValues (
**/
BOOLEAN
CompareRedfishNumericArrayValues (
- IN RedfishCS_int64_Array *Head,
- IN INT64 *NumericArray,
- IN UINTN ArraySize
+ IN RedfishCS_int64_Array *Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
);
/**
@@ -935,10 +937,10 @@ CompareRedfishBooleanArrayValues (
**/
BOOLEAN
CompareRedfishPropertyVagueValues (
- IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
- IN UINT32 RedfishVagueKeyValueNumber,
- IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
- IN UINT32 ConfigVagueKeyValueNumber
+ IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
+ IN UINT32 RedfishVagueKeyValueNumber,
+ IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
+ IN UINT32 ConfigVagueKeyValueNumber
);
/**
@@ -955,9 +957,31 @@ CompareRedfishPropertyVagueValues (
**/
EFI_STATUS
GetEtagAndLocation (
- IN REDFISH_RESPONSE *Response,
- OUT CHAR8 **Etag, OPTIONAL
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag, OPTIONAL
OUT EFI_STRING *Location OPTIONAL
);
+/**
+
+ Check and see if "@Redfish.Settings" exist in given Payload. If found,
return the
+ payload and URI to pending settings. Caller has to release "SettingPayload"
and
+ "SettingUri".
+
+ @param[in] Payload Payload that may contain "@Redfish.Settings"
+ @param[out] SettingPayload Payload keeps pending settings.
+ @param[out] SettingUri URI to pending settings.
+
+ @retval EFI_SUCCESS Pending settings is found and returned.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+GetPendingSettings (
+ IN REDFISH_SERVICE RedfishService,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *SettingResponse,
+ OUT EFI_STRING *SettingUri
+ );
+
#endif
diff --git
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
index bfd6fff2a7..d95d399462 100644
---
a/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
+++
b/RedfishClientPkg/Library/RedfishFeatureUtilityLib/RedfishFeatureUtilityLib
.c
@@ -2,7 +2,7 @@
Redfish feature utility library implementation
(C) Copyright 2020-2022 Hewlett Packard Enterprise Development LP<BR>
- Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,7 +10,7 @@
#include "RedfishFeatureUtilityInternal.h"
-EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol = NULL;
+EDKII_REDFISH_ETAG_PROTOCOL *mEtagProtocol = NULL;
EDKII_REDFISH_CONFIG_LANG_MAP_PROTOCOL
*mConfigLangMapProtocol = NULL;
/**
@@ -33,7 +33,7 @@ RedfishLocateProtocol (
{
EFI_STATUS Status;
- if (ProtocolInstance == NULL || ProtocolGuid == NULL) {
+ if ((ProtocolInstance == NULL) || (ProtocolGuid == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -62,14 +62,14 @@ RedfishLocateProtocol (
**/
EFI_STATUS
GetArraykeyFromUri (
- IN CHAR8 *Uri,
- OUT CHAR8 **ArrayKey
+ IN CHAR8 *Uri,
+ OUT CHAR8 **ArrayKey
)
{
- CHAR8 *LeftBracket;
- UINTN Index;
+ CHAR8 *LeftBracket;
+ UINTN Index;
- if (IS_EMPTY_STRING (Uri) || ArrayKey == NULL) {
+ if (IS_EMPTY_STRING (Uri) || (ArrayKey == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -207,19 +207,19 @@ GetEtagWithUri (
**/
CHAR8 *
StrUnicodeToAscii (
- IN EFI_STRING UnicodeStr
+ IN EFI_STRING UnicodeStr
)
{
- CHAR8 *AsciiStr;
- UINTN AsciiStrSize;
- EFI_STATUS Status;
+ CHAR8 *AsciiStr;
+ UINTN AsciiStrSize;
+ EFI_STATUS Status;
if (IS_EMPTY_STRING (UnicodeStr)) {
return NULL;
}
AsciiStrSize = StrLen (UnicodeStr) + 1;
- AsciiStr = AllocatePool (AsciiStrSize);
+ AsciiStr = AllocatePool (AsciiStrSize);
if (AsciiStr == NULL) {
return NULL;
}
@@ -258,7 +258,7 @@ StrAsciiToUnicode (
}
UnicodeStrSize = (AsciiStrLen (AsciiStr) + 1) * sizeof (CHAR16);
- UnicodeStr = AllocatePool (UnicodeStrSize);
+ UnicodeStr = AllocatePool (UnicodeStrSize);
if (UnicodeStr == NULL) {
return NULL;
}
@@ -288,16 +288,16 @@ StrAsciiToUnicode (
**/
EFI_STATUS
ApplyFeatureSettingsStringType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN CHAR8 *FeatureValue
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN CHAR8 *FeatureValue
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || FeatureValue == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || (FeatureValue == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -308,9 +308,8 @@ ApplyFeatureSettingsStringType (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
} else {
-
if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
return EFI_DEVICE_ERROR;
}
@@ -350,14 +349,14 @@ ApplyFeatureSettingsStringType (
**/
EFI_STATUS
ApplyFeatureSettingsNumericType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN INTN FeatureValue
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN INTN FeatureValue
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang)) {
return EFI_INVALID_PARAMETER;
@@ -368,11 +367,10 @@ ApplyFeatureSettingsNumericType (
//
Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
&RedfishValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
} else {
-
if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not numeric type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
return EFI_DEVICE_ERROR;
}
@@ -411,14 +409,14 @@ ApplyFeatureSettingsNumericType (
**/
EFI_STATUS
ApplyFeatureSettingsBooleanType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN BOOLEAN FeatureValue
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN BOOLEAN FeatureValue
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang)) {
return EFI_INVALID_PARAMETER;
@@ -429,11 +427,10 @@ ApplyFeatureSettingsBooleanType (
//
Status = RedfishPlatformConfigGetValue (Schema, Version, ConfigureLang,
&RedfishValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
} else {
-
if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not boolean type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
return EFI_DEVICE_ERROR;
}
@@ -473,32 +470,35 @@ ApplyFeatureSettingsBooleanType (
**/
EFI_STATUS
ApplyFeatureSettingsVagueType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
- IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
- IN UINT32 NumberOfVagueValues
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
+ IN RedfishCS_EmptyProp_KeyValue *VagueValuePtr,
+ IN UINT32 NumberOfVagueValues
)
{
- EFI_STATUS Status;
- UINTN StrSize;
- CHAR8 *ConfigureLangAscii;
- CHAR8 *ConfigureLangKeyAscii;
- EFI_STRING ConfigureKeyLang;
- EDKII_REDFISH_VALUE RedfishValue;
- EDKII_REDFISH_VALUE_TYPES PropertyDatatype;
- RedfishCS_EmptyProp_KeyValue *CurrentVagueValuePtr;
-
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || VagueValuePtr == NULL ||
NumberOfVagueValues == 0) {
+ EFI_STATUS Status;
+ UINTN StrSize;
+ CHAR8 *ConfigureLangAscii;
+ CHAR8 *ConfigureLangKeyAscii;
+ EFI_STRING ConfigureKeyLang;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EDKII_REDFISH_VALUE_TYPES PropertyDatatype;
+ RedfishCS_EmptyProp_KeyValue *CurrentVagueValuePtr;
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || (VagueValuePtr == NULL) ||
(NumberOfVagueValues == 0)) {
return EFI_INVALID_PARAMETER;
}
+ DEBUG ((REDFISH_DEBUG_TRACE, "%a: schema: %a %a config lang: %s
NumberOfVagueValues: %d\n", __FUNCTION__, Schema, Version,
ConfigureLang, NumberOfVagueValues));
+
ConfigureLangAscii = AllocatePool (StrLen (ConfigureLang) + 1);
if (ConfigureLangAscii == NULL) {
Status = EFI_OUT_OF_RESOURCES;
DEBUG ((DEBUG_ERROR, "%a, Allocate memory for generate
ConfigureLang of vague key of %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
return Status;
}
+
Status = UnicodeStrToAsciiStrS (ConfigureLang, ConfigureLangAscii, StrLen
(ConfigureLang) + 1);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, Convert the configureLang of vague key of
%a.%a %s failed: %r\n", __FUNCTION__, Schema, Version, ConfigureLang,
Status));
@@ -510,18 +510,19 @@ ApplyFeatureSettingsVagueType (
//
// Generate ConfigureLang with the key name
//
- //ConfigureKeyLang = GetConfigureLang (ConfigureLangAscii,
CurrentVagueValuePtr->KeyNamePtr);
- StrSize = AsciiStrLen (ConfigureLangAscii) + AsciiStrLen
(CurrentVagueValuePtr->KeyNamePtr) + 2;
+ // ConfigureKeyLang = GetConfigureLang (ConfigureLangAscii,
CurrentVagueValuePtr->KeyNamePtr);
+ StrSize = AsciiStrLen (ConfigureLangAscii) + AsciiStrLen
(CurrentVagueValuePtr->KeyNamePtr) + 2;
ConfigureLangKeyAscii = AllocateZeroPool (StrSize);
- ConfigureKeyLang = AllocateZeroPool (StrSize * sizeof (CHAR16));
- if (ConfigureLangKeyAscii == NULL || ConfigureKeyLang == NULL) {
- DEBUG ((DEBUG_ERROR, "%a, Generate ConfigureLang of vague key of
%a.%a %s %a failed!\n", __FUNCTION__, Schema, Version, ConfigureLang,
CurrentVagueValuePtr->KeyNamePtr));
- goto ErrorContinue;
+ ConfigureKeyLang = AllocateZeroPool (StrSize * sizeof (CHAR16));
+ if ((ConfigureLangKeyAscii == NULL) || (ConfigureKeyLang == NULL)) {
+ DEBUG ((DEBUG_ERROR, "%a, Generate ConfigureLang of vague key of
%a.%a %s %a failed!\n", __FUNCTION__, Schema, Version, ConfigureLang,
CurrentVagueValuePtr->KeyNamePtr));
+ goto ErrorContinue;
}
- AsciiStrCatS(ConfigureLangKeyAscii, StrSize, ConfigureLangAscii);
- AsciiStrCatS(ConfigureLangKeyAscii, StrSize, "/");
- AsciiStrCatS(ConfigureLangKeyAscii, StrSize, CurrentVagueValuePtr-KeyNamePtr);- AsciiStrToUnicodeStrS(ConfigureLangKeyAscii, ConfigureKeyLang, StrSize);
+
+ AsciiStrCatS (ConfigureLangKeyAscii, StrSize, ConfigureLangAscii);
+ AsciiStrCatS (ConfigureLangKeyAscii, StrSize, "/");
+ AsciiStrCatS (ConfigureLangKeyAscii, StrSize, CurrentVagueValuePtr-KeyNamePtr);+ AsciiStrToUnicodeStrS (ConfigureLangKeyAscii, ConfigureKeyLang,
StrSize);
FreePool (ConfigureLangKeyAscii);
ConfigureLangKeyAscii = NULL;
//
@@ -534,7 +535,7 @@ ApplyFeatureSettingsVagueType (
} else if (CurrentVagueValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Int64) {
PropertyDatatype = REDFISH_VALUE_TYPE_INTEGER;
} else {
- DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property
data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property
data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
goto ErrorContinue;
}
@@ -546,9 +547,10 @@ ApplyFeatureSettingsVagueType (
DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureKeyLang, Status));
} else {
if (RedfishValue.Type != PropertyDatatype) {
- DEBUG((DEBUG_ERROR, "%a, %a.%a %s mismatched data type\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s mismatched data type\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang));
goto ErrorContinue;
}
+
if (PropertyDatatype == REDFISH_VALUE_TYPE_STRING) {
//
// This is a string property.
@@ -560,7 +562,7 @@ ApplyFeatureSettingsVagueType (
DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Buffer, CurrentVagueValuePtr->Value-DataValue.CharPtr));FreePool (RedfishValue.Value.Buffer);
RedfishValue.Value.Buffer = CurrentVagueValuePtr->Value-DataValue.CharPtr;- Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, apply %a to %a failed: %r\n",
__FUNCTION__, ConfigureKeyLang, CurrentVagueValuePtr->Value-DataValue.CharPtr, Status));}
@@ -575,16 +577,19 @@ ApplyFeatureSettingsVagueType (
//
// Apply settings from redfish
//
- DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from %a to %a\n",
- __FUNCTION__,
- Schema,
- Version,
- ConfigureKeyLang,
- (RedfishValue.Value.Boolean ? "True" : "False"),
- (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "True" :
"False")));
+ DEBUG ((
+ DEBUG_INFO,
+ "%a, %a.%a apply %s from %a to %a\n",
+ __FUNCTION__,
+ Schema,
+ Version,
+ ConfigureKeyLang,
+ (RedfishValue.Value.Boolean ? "True" : "False"),
+ (*CurrentVagueValuePtr->Value->DataValue.BoolPtr ? "True" :
"False")
+ ));
RedfishValue.Value.Boolean = (BOOLEAN)*CurrentVagueValuePtr-Value->DataValue.BoolPtr;- Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, apply %s to %a failed: %r\n",
__FUNCTION__, ConfigureKeyLang, (*CurrentVagueValuePtr->Value-DataValue.BoolPtr ? "True" : "False"), Status));}
@@ -602,7 +607,7 @@ ApplyFeatureSettingsVagueType (
DEBUG ((DEBUG_INFO, "%a, %a.%a apply %s from 0x%x to 0x%x\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Integer, *CurrentVagueValuePtr->Value-DataValue.Int64Ptr));RedfishValue.Value.Integer = (INT64)*CurrentVagueValuePtr->Value-DataValue.Int64Ptr;- Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
+ Status = RedfishPlatformConfigSetValue (Schema, Version,
ConfigureKeyLang, RedfishValue);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, apply %s to 0x%x failed: %r\n",
__FUNCTION__, ConfigureKeyLang, *CurrentVagueValuePtr->Value-DataValue.Int64Ptr, Status));}
@@ -610,7 +615,7 @@ ApplyFeatureSettingsVagueType (
DEBUG ((DEBUG_INFO, "%a, %a.%a %s value is: 0x%x\n",
__FUNCTION__, Schema, Version, ConfigureKeyLang,
RedfishValue.Value.Integer, Status));
}
} else {
- DEBUG((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish property
data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s Unsupported Redfish
property data type\n", __FUNCTION__, Schema, Version, ConfigureLang));
goto ErrorContinue;
}
}
@@ -620,22 +625,27 @@ ErrorContinue:;
FreePool (ConfigureLangKeyAscii);
ConfigureLangKeyAscii = NULL;
}
+
if (ConfigureKeyLang != NULL) {
FreePool (ConfigureKeyLang);
ConfigureKeyLang = NULL;
}
+
CurrentVagueValuePtr = CurrentVagueValuePtr->NextKeyValuePtr;
- };
+ }
if (ConfigureLangAscii != NULL) {
FreePool (ConfigureLangAscii);
}
+
if (ConfigureLangKeyAscii != NULL) {
FreePool (ConfigureLangKeyAscii);
}
+
if (ConfigureKeyLang != NULL) {
FreePool (ConfigureKeyLang);
}
+
return EFI_SUCCESS;
}
@@ -648,16 +658,16 @@ ErrorContinue:;
**/
VOID
FreeArrayTypeRedfishValue (
- EDKII_REDFISH_VALUE *RedfishValue
+ EDKII_REDFISH_VALUE *RedfishValue
)
{
- UINTN Index;
+ UINTN Index;
if (RedfishValue == NULL) {
return;
}
- if (RedfishValue->Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY &&
RedfishValue->Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
+ if ((RedfishValue->Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) &&
(RedfishValue->Type != REDFISH_VALUE_TYPE_STRING_ARRAY)) {
return;
}
@@ -666,6 +676,7 @@ FreeArrayTypeRedfishValue (
for (Index = 0; Index < RedfishValue->ArrayCount; Index++) {
FreePool (RedfishValue->Value.StringArray[Index]);
}
+
FreePool (RedfishValue->Value.StringArray);
RedfishValue->Value.StringArray = NULL;
break;
@@ -687,7 +698,6 @@ FreeArrayTypeRedfishValue (
RedfishValue->ArrayCount = 0;
}
-
/**
Apply property value to UEFI HII database in string array type.
@@ -714,7 +724,7 @@ ApplyFeatureSettingsStringArrayType (
UINTN Index;
RedfishCS_char_Array *Buffer;
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -725,9 +735,8 @@ ApplyFeatureSettingsStringArrayType (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
} else {
-
if (RedfishValue.Type != REDFISH_VALUE_TYPE_STRING_ARRAY) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
return EFI_DEVICE_ERROR;
}
@@ -745,10 +754,10 @@ ApplyFeatureSettingsStringArrayType (
// Convert array from RedfishCS_char_Array to EDKII_REDFISH_VALUE
//
RedfishValue.ArrayCount = 0;
- Buffer = ArrayHead;
+ Buffer = ArrayHead;
while (Buffer != NULL) {
RedfishValue.ArrayCount += 1;
- Buffer = Buffer->Next;
+ Buffer = Buffer->Next;
}
//
@@ -761,13 +770,14 @@ ApplyFeatureSettingsStringArrayType (
}
Buffer = ArrayHead;
- Index = 0;
+ Index = 0;
while (Buffer != NULL) {
RedfishValue.Value.StringArray[Index] = AllocateCopyPool (AsciiStrSize
(Buffer->ArrayValue), Buffer->ArrayValue);
if (RedfishValue.Value.StringArray[Index] == NULL) {
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
+
Buffer = Buffer->Next;
Index++;
}
@@ -801,18 +811,18 @@ ApplyFeatureSettingsStringArrayType (
**/
EFI_STATUS
ApplyFeatureSettingsNumericArrayType (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING ConfigureLang,
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING ConfigureLang,
IN RedfishCS_int64_Array *ArrayHead
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- UINTN Index;
- RedfishCS_int64_Array *Buffer;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ UINTN Index;
+ RedfishCS_int64_Array *Buffer;
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -823,7 +833,6 @@ ApplyFeatureSettingsNumericArrayType (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
} else {
-
if (RedfishValue.Type != REDFISH_VALUE_TYPE_INTEGER_ARRAY) {
DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
return EFI_DEVICE_ERROR;
@@ -843,10 +852,10 @@ ApplyFeatureSettingsNumericArrayType (
// Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
//
RedfishValue.ArrayCount = 0;
- Buffer = ArrayHead;
+ Buffer = ArrayHead;
while (Buffer != NULL) {
RedfishValue.ArrayCount += 1;
- Buffer = Buffer->Next;
+ Buffer = Buffer->Next;
}
//
@@ -859,10 +868,10 @@ ApplyFeatureSettingsNumericArrayType (
}
Buffer = ArrayHead;
- Index = 0;
+ Index = 0;
while (Buffer != NULL) {
RedfishValue.Value.IntegerArray[Index] = (INT64)*Buffer->ArrayValue;
- Buffer = Buffer->Next;
+ Buffer = Buffer->Next;
Index++;
}
@@ -904,9 +913,9 @@ ApplyFeatureSettingsBooleanArrayType (
EFI_STATUS Status;
EDKII_REDFISH_VALUE RedfishValue;
UINTN Index;
- RedfishCS_bool_Array *Buffer;
+ RedfishCS_bool_Array *Buffer;
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || ArrayHead == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || (ArrayHead == NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -917,7 +926,6 @@ ApplyFeatureSettingsBooleanArrayType (
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a, %a.%a %s failed: %r\n", __FUNCTION__,
Schema, Version, ConfigureLang, Status));
} else {
-
if (RedfishValue.Type != REDFISH_VALUE_TYPE_BOOLEAN_ARRAY) {
DEBUG ((DEBUG_ERROR, "%a, %a.%a %s value is not string array type\n",
__FUNCTION__, Schema, Version, ConfigureLang));
return EFI_DEVICE_ERROR;
@@ -937,10 +945,10 @@ ApplyFeatureSettingsBooleanArrayType (
// Convert array from RedfishCS_int64_Array to EDKII_REDFISH_VALUE
//
RedfishValue.ArrayCount = 0;
- Buffer = ArrayHead;
+ Buffer = ArrayHead;
while (Buffer != NULL) {
RedfishValue.ArrayCount += 1;
- Buffer = Buffer->Next;
+ Buffer = Buffer->Next;
}
//
@@ -953,10 +961,10 @@ ApplyFeatureSettingsBooleanArrayType (
}
Buffer = ArrayHead;
- Index = 0;
+ Index = 0;
while (Buffer != NULL) {
RedfishValue.Value.BooleanArray[Index] = (BOOLEAN)*Buffer-ArrayValue;- Buffer = Buffer->Next;
+ Buffer = Buffer->Next;
Index++;
}
@@ -988,15 +996,15 @@ ApplyFeatureSettingsBooleanArrayType (
**/
EFI_STATUS
GetResourceByUri (
- IN REDFISH_SERVICE *Service,
- IN EFI_STRING ResourceUri,
- OUT REDFISH_RESPONSE *Response
+ IN REDFISH_SERVICE *Service,
+ IN EFI_STRING ResourceUri,
+ OUT REDFISH_RESPONSE *Response
)
{
EFI_STATUS Status;
CHAR8 *AsciiResourceUri;
- if (Service == NULL || Response == NULL || IS_EMPTY_STRING
(ResourceUri)) {
+ if ((Service == NULL) || (Response == NULL) || IS_EMPTY_STRING
(ResourceUri)) {
return EFI_INVALID_PARAMETER;
}
@@ -1051,9 +1059,9 @@ GetResourceByUri (
**/
EFI_STATUS
IsRedpathArray (
- IN EFI_STRING ConfigureLang,
- OUT EFI_STRING *ArraySignatureOpen OPTIONAL,
- OUT EFI_STRING *ArraySignatureClose OPTIONAL
+ IN EFI_STRING ConfigureLang,
+ OUT EFI_STRING *ArraySignatureOpen OPTIONAL,
+ OUT EFI_STRING *ArraySignatureClose OPTIONAL
)
{
CHAR16 *IndexString;
@@ -1061,9 +1069,11 @@ IsRedpathArray (
if (ConfigureLang == NULL) {
return EFI_INVALID_PARAMETER;
}
+
if (ArraySignatureOpen != NULL) {
*ArraySignatureOpen = NULL;
}
+
if (ArraySignatureClose != NULL) {
*ArraySignatureClose = NULL;
}
@@ -1076,6 +1086,7 @@ IsRedpathArray (
if (ArraySignatureOpen != NULL) {
*ArraySignatureOpen = IndexString;
}
+
//
// Skip "{"
//
@@ -1087,11 +1098,14 @@ IsRedpathArray (
if (IndexString == NULL) {
return EFI_INVALID_PARAMETER;
}
+
if (ArraySignatureClose != NULL) {
*ArraySignatureClose = IndexString;
}
+
return EFI_SUCCESS;
}
+
return EFI_NOT_FOUND;
}
@@ -1106,23 +1120,25 @@ IsRedpathArray (
**/
UINTN
GetNumberOfRedpathNodes (
- IN EFI_STRING NodeString
+ IN EFI_STRING NodeString
)
{
- UINTN Index;
- UINTN NumberNodes;
- UINTN StringLen;
+ UINTN Index;
+ UINTN NumberNodes;
+ UINTN StringLen;
NumberNodes = 0;
- StringLen = StrLen (NodeString);
- Index = 1; // ConfigLang always starts with '/'.
+ StringLen = StrLen (NodeString);
+ Index = 1; // ConfigLang always starts with '/'.
while (Index < StringLen) {
if (*(NodeString + Index) == L'/') {
- NumberNodes ++;
+ NumberNodes++;
}
- Index ++;
- };
- NumberNodes ++;
+
+ Index++;
+ }
+
+ NumberNodes++;
return (NumberNodes);
}
@@ -1141,24 +1157,25 @@ GetNumberOfRedpathNodes (
**/
EFI_STRING
GetRedpathNodeByIndex (
- IN EFI_STRING NodeString,
- IN UINTN Index,
- OUT EFI_STRING *EndOfNodePtr OPTIONAL
+ IN EFI_STRING NodeString,
+ IN UINTN Index,
+ OUT EFI_STRING *EndOfNodePtr OPTIONAL
)
{
- UINTN NumberNodes;
- UINTN StringLen;
- UINTN StringIndex;
- EFI_STRING NodeStart;
- EFI_STRING NodeEnd;
+ UINTN NumberNodes;
+ UINTN StringLen;
+ UINTN StringIndex;
+ EFI_STRING NodeStart;
+ EFI_STRING NodeEnd;
NumberNodes = 0;
- StringLen = StrLen (NodeString);
+ StringLen = StrLen (NodeString);
StringIndex = 1; // ConfigLang always starts with '/'.
- NodeStart = NodeString;
+ NodeStart = NodeString;
if (EndOfNodePtr != NULL) {
*EndOfNodePtr = NULL;
}
+
while (StringIndex < StringLen) {
if (*(NodeString + StringIndex) == L'/') {
NodeEnd = NodeString + StringIndex - 1;
@@ -1166,14 +1183,17 @@ GetRedpathNodeByIndex (
if (EndOfNodePtr != NULL) {
*EndOfNodePtr = NodeEnd;
}
+
return NodeStart;
} else {
NodeStart = NodeString + StringIndex + 1;
}
}
- StringIndex ++;
- };
- return (NULL);
+
+ StringIndex++;
+ }
+
+ return (NULL);
}
/**
@@ -1192,18 +1212,18 @@ GetRedpathNodeByIndex (
**/
EFI_STATUS
GetArrayIndexFromArrayTypeConfigureLang (
- IN CHAR16 *ConfigureLang,
- OUT CHAR16 **UnifiedConfigureLang,
- OUT UINTN *Index
+ IN CHAR16 *ConfigureLang,
+ OUT CHAR16 **UnifiedConfigureLang,
+ OUT UINTN *Index
)
{
- EFI_STATUS Status;
- CHAR16 *TmpConfigureLang;
- CHAR16 *ArrayOpenStr;
- CHAR16 *ArrayCloseStr;
- INTN StringIndex;
+ EFI_STATUS Status;
+ CHAR16 *TmpConfigureLang;
+ CHAR16 *ArrayOpenStr;
+ CHAR16 *ArrayCloseStr;
+ INTN StringIndex;
- if (ConfigureLang == NULL || UnifiedConfigureLang == NULL || Index ==
NULL) {
+ if ((ConfigureLang == NULL) || (UnifiedConfigureLang == NULL) || (Index
== NULL)) {
return EFI_INVALID_PARAMETER;
}
@@ -1227,28 +1247,30 @@ GetArrayIndexFromArrayTypeConfigureLang (
//
// Resotre the '}' character and remove rest of string.
//
- ArrayCloseStr[0] = L'}';
- ArrayCloseStr[1] = '\0';
+ ArrayCloseStr[0] = L'}';
+ ArrayCloseStr[1] = '\0';
*UnifiedConfigureLang = TmpConfigureLang;
} else {
if (Status == EFI_NOT_FOUND) {
//
// This is not the redpath array. Search "/" for the parent root.
//
- *Index = 0;
+ *Index = 0;
StringIndex = StrLen (TmpConfigureLang) - 1;
while (StringIndex >= 0 && *(TmpConfigureLang + StringIndex) != '/') {
- StringIndex --;
- };
+ StringIndex--;
+ }
+
if (StringIndex >= 0 ) {
*(TmpConfigureLang + StringIndex) = '\0';
- *UnifiedConfigureLang = TmpConfigureLang;
- Status = EFI_SUCCESS;
+ *UnifiedConfigureLang = TmpConfigureLang;
+ Status = EFI_SUCCESS;
} else {
Status = EFI_INVALID_PARAMETER;
}
}
}
+
return Status;
}
@@ -1265,27 +1287,30 @@ GetArrayIndexFromArrayTypeConfigureLang (
**/
EFI_STATUS
CopyConfiglanguageList (
- IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
- OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*SourceConfigureLangList,
+ OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*DestConfigureLangList
)
{
- UINTN Index;
+ UINTN Index;
- if (SourceConfigureLangList == NULL || DestConfigureLangList == NULL) {
+ if ((SourceConfigureLangList == NULL) || (DestConfigureLangList == NULL))
{
return EFI_INVALID_PARAMETER;
}
+
DestConfigureLangList->Count = SourceConfigureLangList->Count;
- DestConfigureLangList->List =
- (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *)AllocateZeroPool
(sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
DestConfigureLangList->Count);
+ DestConfigureLangList->List =
+ (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *)AllocateZeroPool
(sizeof (REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG) *
DestConfigureLangList->Count);
if (DestConfigureLangList->List == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG.\n", __FUNCTION__));
return EFI_OUT_OF_RESOURCES;
}
+
for (Index = 0; Index < SourceConfigureLangList->Count; Index++) {
- DestConfigureLangList->List [Index].Index = SourceConfigureLangList-List[Index].Index;- DestConfigureLangList->List [Index].ConfigureLang =
- (EFI_STRING)AllocateCopyPool(StrSize(SourceConfigureLangList-List[Index].ConfigureLang), (VOID *)SourceConfigureLangList-+ DestConfigureLangList->List[Index].Index = SourceConfigureLangList-
List[Index].ConfigureLang);List[Index].Index;+ DestConfigureLangList->List[Index].ConfigureLang =
+ (EFI_STRING)AllocateCopyPool (StrSize (SourceConfigureLangList-List[Index].ConfigureLang), (VOID *)SourceConfigureLangList-}
List[Index].ConfigureLang);
+
return EFI_SUCCESS;
}
@@ -1300,39 +1325,45 @@ CopyConfiglanguageList (
**/
UINTN
ConfiglanguageGetInstanceIndex (
- IN EFI_STRING ConfigureLang
+ IN EFI_STRING ConfigureLang
)
{
- INTN LeftBracketIndex;
- INTN RightBracketIndex;
- INTN Index;
- UINT64 Instance;
- EFI_STATUS Status;
+ INTN LeftBracketIndex;
+ INTN RightBracketIndex;
+ INTN Index;
+ UINT64 Instance;
+ EFI_STATUS Status;
if (ConfigureLang == NULL) {
return 0;
}
- LeftBracketIndex = 0;
+
+ LeftBracketIndex = 0;
RightBracketIndex = 0;
- Index = StrLen (ConfigureLang) - 1;
+ Index = StrLen (ConfigureLang) - 1;
while (Index >= 0) {
if (*(ConfigureLang + Index) == L'{') {
LeftBracketIndex = Index;
break;
}
+
if (*(ConfigureLang + Index) == L'}') {
RightBracketIndex = Index;
}
- Index --;
- };
+
+ Index--;
+ }
+
if ((RightBracketIndex - LeftBracketIndex) <= 1) {
return 0;
}
+
*(ConfigureLang + RightBracketIndex) = 0;
- Status = StrDecimalToUint64S (ConfigureLang + LeftBracketIndex + 1, NULL,
&Instance);
- if (EFI_ERROR(Status)) {
+ Status = StrDecimalToUint64S (ConfigureLang +
LeftBracketIndex + 1, NULL, &Instance);
+ if (EFI_ERROR (Status)) {
Instance = 0;
}
+
//
// Restore right curly bracket.
//
@@ -1353,20 +1384,22 @@ ConfiglanguageGetInstanceIndex (
**/
EFI_STATUS
DestroyConfiglanguageList (
- IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*ConfigureLangList
)
{
- UINTN Index;
+ UINTN Index;
if (ConfigureLangList == NULL) {
return EFI_INVALID_PARAMETER;
}
+
if (ConfigureLangList->List != NULL) {
for (Index = 0; Index < ConfigureLangList->Count; Index++) {
- if (ConfigureLangList->List [Index].ConfigureLang != NULL) {
- FreePool (ConfigureLangList->List [Index].ConfigureLang);
+ if (ConfigureLangList->List[Index].ConfigureLang != NULL) {
+ FreePool (ConfigureLangList->List[Index].ConfigureLang);
}
}
+
FreePool (ConfigureLangList->List);
ConfigureLangList->List = NULL;
}
@@ -1391,56 +1424,60 @@ DestroyConfiglanguageList (
**/
EFI_STATUS
SetResourceConfigLangMemberInstance (
- IN EFI_STRING *DestConfigLang,
- IN UINTN MaxtLengthConfigLang,
- IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance
+ IN EFI_STRING *DestConfigLang,
+ IN UINTN MaxtLengthConfigLang,
+ IN REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG *ConfigLangInstance
)
{
- EFI_STRING ThisConfigLang;
- EFI_STRING NewConfigLang;
- CHAR16 InstanceStr [10];
- INTN Index;
- UINTN Length;
- UINTN MaxStrLength;
-
- if (DestConfigLang == NULL || ConfigLangInstance == NULL) {
+ EFI_STRING ThisConfigLang;
+ EFI_STRING NewConfigLang;
+ CHAR16 InstanceStr[10];
+ INTN Index;
+ UINTN Length;
+ UINTN MaxStrLength;
+
+ if ((DestConfigLang == NULL) || (ConfigLangInstance == NULL)) {
return EFI_INVALID_PARAMETER;
}
+
UnicodeSPrint ((CHAR16 *)&InstanceStr, 10, L"%d", ConfigLangInstance-Index);ThisConfigLang = *DestConfigLang;
- if (ThisConfigLang [0] == 0) {
+ if (ThisConfigLang[0] == 0) {
//
// Return ConfigLangInstance->ConfigureLang
//
if (ConfigLangInstance->ConfigureLang == NULL) {
return EFI_INVALID_PARAMETER;
} else {
- StrCatS(*DestConfigLang, MaxtLengthConfigLang, ConfigLangInstance-ConfigureLang);+ StrCatS (*DestConfigLang, MaxtLengthConfigLang, ConfigLangInstance-ConfigureLang);return EFI_SUCCESS;
}
}
- MaxStrLength = StrSize (ThisConfigLang) + StrSize
((EFI_STRING)&InstanceStr);
+ MaxStrLength = StrSize (ThisConfigLang) + StrSize
((EFI_STRING)&InstanceStr);
NewConfigLang = ThisConfigLang;
if (MaxtLengthConfigLang < MaxStrLength) {
- NewConfigLang = (EFI_STRING)AllocateZeroPool(MaxStrLength);
+ NewConfigLang = (EFI_STRING)AllocateZeroPool (MaxStrLength);
if (NewConfigLang == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Fail to allocate memory for
NewConfigLang.\n", __FUNCTION__));
return EFI_OUT_OF_RESOURCES;
}
}
+
//
// Search the last "{"
//
Index = StrLen (ThisConfigLang) - 1;
while ((ThisConfigLang[Index] != '{') && (Index >= 0)) {
- Index --;
- };
+ Index--;
+ }
+
if (Index == -1) {
if (NewConfigLang != ThisConfigLang) {
- FreePool(NewConfigLang);
+ FreePool (NewConfigLang);
}
+
return EFI_NOT_FOUND;
}
@@ -1449,15 +1486,17 @@ SetResourceConfigLangMemberInstance (
//
Length = 0;
while (Index >= 0) {
- NewConfigLang [Index] = ThisConfigLang[Index];
- Index --;
- Length ++;
- };
+ NewConfigLang[Index] = ThisConfigLang[Index];
+ Index--;
+ Length++;
+ }
+
UnicodeSPrint ((CHAR16 *)(NewConfigLang + Length), MaxStrLength,
L"%d", ConfigLangInstance->Index);
StrCatS (NewConfigLang, MaxStrLength, L"}");
if (NewConfigLang != ThisConfigLang) {
FreePool (ThisConfigLang);
}
+
*DestConfigLang = NewConfigLang;
return EFI_SUCCESS;
}
@@ -1478,28 +1517,28 @@ SetResourceConfigLangMemberInstance (
**/
EFI_STATUS
RedfishFeatureGetUnifiedArrayTypeConfigureLang (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING Pattern, OPTIONAL
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING Pattern, OPTIONAL
OUT REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG_LIST
*UnifiedConfigureLangList
)
{
- EFI_STATUS Status;
- EFI_STRING *ConfigureLangList;
- UINTN Count;
- UINTN Index;
- UINTN Index2;
- UINTN ArrayIndex;
- EFI_STRING UnifiedConfigureLang;
- BOOLEAN Duplicated;
- REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
E];
-
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
UnifiedConfigureLangList == NULL) {
+ EFI_STATUS Status;
+ EFI_STRING *ConfigureLangList;
+ UINTN Count;
+ UINTN Index;
+ UINTN Index2;
+ UINTN ArrayIndex;
+ EFI_STRING UnifiedConfigureLang;
+ BOOLEAN Duplicated;
+ REDFISH_FEATURE_ARRAY_TYPE_CONFIG_LANG
UnifiedConfigureLangPool[BIOS_CONFIG_TO_REDFISH_REDPATH_POOL_SIZ
E];
+
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
(UnifiedConfigureLangList == NULL)) {
return EFI_INVALID_PARAMETER;
}
UnifiedConfigureLangList->Count = 0;
- UnifiedConfigureLangList->List = NULL;
+ UnifiedConfigureLangList->List = NULL;
ZeroMem (UnifiedConfigureLangPool, sizeof (UnifiedConfigureLangPool));
Status = RedfishPlatformConfigGetConfigureLang (Schema, Version,
Pattern, &ConfigureLangList, &Count);
@@ -1514,7 +1553,7 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang
(
for (Index = 0; Index < Count; Index++) {
Status = GetArrayIndexFromArrayTypeConfigureLang
(ConfigureLangList[Index], &UnifiedConfigureLang, &ArrayIndex);
- if (EFI_ERROR (Status) && Status == EFI_INVALID_PARAMETER) {
+ if (EFI_ERROR (Status) && (Status == EFI_INVALID_PARAMETER)) {
ASSERT (FALSE);
continue;
}
@@ -1550,7 +1589,7 @@ RedfishFeatureGetUnifiedArrayTypeConfigureLang
(
//
UnifiedConfigureLangPool[UnifiedConfigureLangList-Count].ConfigureLang = UnifiedConfigureLang;- UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =
ArrayIndex;
+ UnifiedConfigureLangPool[UnifiedConfigureLangList->Count].Index =
ArrayIndex;
++UnifiedConfigureLangList->Count;
}
@@ -1578,23 +1617,23 @@
RedfishFeatureGetUnifiedArrayTypeConfigureLang (
**/
EFI_STATUS
GetEtagAndLocation (
- IN REDFISH_RESPONSE *Response,
- OUT CHAR8 **Etag, OPTIONAL
+ IN REDFISH_RESPONSE *Response,
+ OUT CHAR8 **Etag, OPTIONAL
OUT EFI_STRING *Location OPTIONAL
)
{
- EDKII_JSON_VALUE JsonValue;
- EDKII_JSON_VALUE OdataValue;
- CHAR8 *OdataString;
- CHAR8 *AsciiLocation;
- EFI_HTTP_HEADER *Header;
- EFI_STATUS Status;
+ EDKII_JSON_VALUE JsonValue;
+ EDKII_JSON_VALUE OdataValue;
+ CHAR8 *OdataString;
+ CHAR8 *AsciiLocation;
+ EFI_HTTP_HEADER *Header;
+ EFI_STATUS Status;
if (Response == NULL) {
return EFI_INVALID_PARAMETER;
}
- if (Etag == NULL && Location == NULL) {
+ if ((Etag == NULL) && (Location == NULL)) {
return EFI_SUCCESS;
}
@@ -1614,7 +1653,7 @@ GetEtagAndLocation (
//
// No header is returned. Search payload for location.
//
- if (*Etag == NULL && Response->Payload != NULL) {
+ if ((*Etag == NULL) && (Response->Payload != NULL)) {
JsonValue = RedfishJsonInPayload (Response->Payload);
if (JsonValue != NULL) {
OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.etag");
@@ -1649,7 +1688,7 @@ GetEtagAndLocation (
//
// No header is returned. Search payload for location.
//
- if (*Location == NULL && Response->Payload != NULL) {
+ if ((*Location == NULL) && (Response->Payload != NULL)) {
JsonValue = RedfishJsonInPayload (Response->Payload);
if (JsonValue != NULL) {
OdataValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
"@odata.id");
@@ -1675,6 +1714,7 @@ GetEtagAndLocation (
return Status;
}
+
/**
Create HTTP payload and send them to redfish service with PATCH method.
@@ -1690,25 +1730,25 @@ GetEtagAndLocation (
**/
EFI_STATUS
CreatePayloadToPatchResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT CHAR8 **Etag
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT CHAR8 **Etag
)
{
- REDFISH_PAYLOAD Payload;
- EDKII_JSON_VALUE ResourceJsonValue;
- REDFISH_RESPONSE PostResponse;
- EFI_STATUS Status;
+ REDFISH_PAYLOAD Payload;
+ EDKII_JSON_VALUE ResourceJsonValue;
+ REDFISH_RESPONSE PostResponse;
+ EFI_STATUS Status;
- if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Etag == NULL) {
+ if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
(Json) || (Etag == NULL)) {
return EFI_INVALID_PARAMETER;
}
ResourceJsonValue = JsonLoadString (Json, 0, NULL);
- Payload = RedfishCreatePayload (ResourceJsonValue, Service);
+ Payload = RedfishCreatePayload (ResourceJsonValue, Service);
if (Payload == NULL) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n", __FUNCTION__, __LINE__));
Status = EFI_DEVICE_ERROR;
goto EXIT_FREE_JSON_VALUE;
}
@@ -1716,7 +1756,7 @@ CreatePayloadToPatchResource (
ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
Status = RedfishPatchToPayload (TargetPayload, Payload, &PostResponse);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
service.\n",__FUNCTION__, __LINE__));
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to PATCH payload to Redfish
service.\n", __FUNCTION__, __LINE__));
goto EXIT_FREE_JSON_VALUE;
}
@@ -1761,26 +1801,26 @@ EXIT_FREE_JSON_VALUE:
**/
EFI_STATUS
CreatePayloadToPostResource (
- IN REDFISH_SERVICE *Service,
- IN REDFISH_PAYLOAD *TargetPayload,
- IN CHAR8 *Json,
- OUT EFI_STRING *Location,
- OUT CHAR8 **Etag
+ IN REDFISH_SERVICE *Service,
+ IN REDFISH_PAYLOAD *TargetPayload,
+ IN CHAR8 *Json,
+ OUT EFI_STRING *Location,
+ OUT CHAR8 **Etag
)
{
- REDFISH_PAYLOAD Payload;
- EDKII_JSON_VALUE ResourceJsonValue;
- REDFISH_RESPONSE PostResponse;
- EFI_STATUS Status;
+ REDFISH_PAYLOAD Payload;
+ EDKII_JSON_VALUE ResourceJsonValue;
+ REDFISH_RESPONSE PostResponse;
+ EFI_STATUS Status;
- if (Service == NULL || TargetPayload == NULL || IS_EMPTY_STRING (Json)
|| Location == NULL || Etag == NULL) {
+ if ((Service == NULL) || (TargetPayload == NULL) || IS_EMPTY_STRING
(Json) || (Location == NULL) || (Etag == NULL)) {
return EFI_INVALID_PARAMETER;
}
ResourceJsonValue = JsonLoadString (Json, 0, NULL);
- Payload = RedfishCreatePayload (ResourceJsonValue, Service);
+ Payload = RedfishCreatePayload (ResourceJsonValue, Service);
if (Payload == NULL) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n",__FUNCTION__, __LINE__));
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to create JSON payload from
JSON value!\n", __FUNCTION__, __LINE__));
Status = EFI_DEVICE_ERROR;
goto EXIT_FREE_JSON_VALUE;
}
@@ -1788,7 +1828,7 @@ CreatePayloadToPostResource (
ZeroMem (&PostResponse, sizeof (REDFISH_RESPONSE));
Status = RedfishPostToPayload (TargetPayload, Payload, &PostResponse);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
Redfish service.\n",__FUNCTION__, __LINE__));
+ DEBUG ((DEBUG_ERROR, "%a:%d Failed to POST Attribute Registry to
Redfish service.\n", __FUNCTION__, __LINE__));
goto EXIT_FREE_JSON_VALUE;
}
@@ -1827,19 +1867,19 @@ EXIT_FREE_JSON_VALUE:
**/
EFI_STRING
RedfishGetUri (
- IN EFI_STRING ConfigLang
+ IN EFI_STRING ConfigLang
)
{
- EFI_STATUS Status;
- EFI_STRING Target;
- EFI_STRING Found;
- EFI_STRING TempStr;
- EFI_STRING ResultStr;
- EFI_STRING Head;
- EFI_STRING CloseBracket;
- UINTN TempStrSize;
- UINTN RemainingLen;
- UINTN ConfigLangLen;
+ EFI_STATUS Status;
+ EFI_STRING Target;
+ EFI_STRING Found;
+ EFI_STRING TempStr;
+ EFI_STRING ResultStr;
+ EFI_STRING Head;
+ EFI_STRING CloseBracket;
+ UINTN TempStrSize;
+ UINTN RemainingLen;
+ UINTN ConfigLangLen;
Status = RedfishLocateProtocol ((VOID **)&mConfigLangMapProtocol,
&gEdkIIRedfishConfigLangMapProtocolGuid);
if (EFI_ERROR (Status)) {
@@ -1875,7 +1915,7 @@ RedfishGetUri (
//
do {
ConfigLangLen = StrLen (Head);
- Target = CloseBracket;
+ Target = CloseBracket;
//
// Look for next ConfigLang
@@ -1895,13 +1935,14 @@ RedfishGetUri (
//
// Copy current ConfigLang to temporary string and do a query
//
- Target += 1;
+ Target += 1;
RemainingLen = StrLen (Target);
- TempStrSize = (ConfigLangLen - RemainingLen + 1) * sizeof (CHAR16);
- TempStr = AllocateCopyPool (TempStrSize, Head);
+ TempStrSize = (ConfigLangLen - RemainingLen + 1) * sizeof (CHAR16);
+ TempStr = AllocateCopyPool (TempStrSize, Head);
if (TempStr == NULL) {
return NULL;
}
+
TempStr[ConfigLangLen - RemainingLen] = '\0';
Status = mConfigLangMapProtocol->Get (
@@ -1926,7 +1967,7 @@ RedfishGetUri (
//
// Prepare for next ConfigLang
//
- Head = Target;
+ Head = Target;
CloseBracket = StrStr (Head, L"{");
} while (CloseBracket != NULL);
@@ -1954,7 +1995,7 @@ RedfishGetUri (
**/
EFI_STRING
RedfishGetConfigLanguage (
- IN EFI_STRING Uri
+ IN EFI_STRING Uri
)
{
EFI_STATUS Status;
@@ -1973,13 +2014,12 @@ RedfishGetConfigLanguage (
}
ConfigLang = NULL;
- Status = mConfigLangMapProtocol->Get (
- mConfigLangMapProtocol,
- RedfishGetTypeUri,
- Uri,
- &ConfigLang
- );
-
+ Status = mConfigLangMapProtocol->Get (
+ mConfigLangMapProtocol,
+ RedfishGetTypeUri,
+ Uri,
+ &ConfigLang
+ );
return ConfigLang;
}
@@ -1997,8 +2037,8 @@ RedfishGetConfigLanguage (
**/
EFI_STRING
GetConfigureLang (
- IN CHAR8 *Uri,
- IN CHAR8 *PropertyName OPTIONAL
+ IN CHAR8 *Uri,
+ IN CHAR8 *PropertyName OPTIONAL
)
{
EFI_STRING ConfigLang;
@@ -2032,12 +2072,14 @@ GetConfigureLang (
}
StringSize = StrSize (ConfigLang) + ((AsciiStrLen (PropertyName) + 1) *
sizeof (CHAR16));
- ResultStr = AllocatePool (StringSize);
+ ResultStr = AllocatePool (StringSize);
if (ResultStr == NULL) {
+ FreePool (ConfigLang);
return NULL;
}
UnicodeSPrint (ResultStr, StringSize, L"%s/%a", ConfigLang, PropertyName);
+ FreePool (ConfigLang);
return ResultStr;
}
@@ -2059,7 +2101,7 @@ RedfisSetRedfishUri (
IN EFI_STRING Uri
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
if (IS_EMPTY_STRING (ConfigLang) || IS_EMPTY_STRING (Uri)) {
return EFI_INVALID_PARAMETER;
@@ -2088,12 +2130,12 @@ RedfisSetRedfishUri (
**/
EFI_STRING
GetOdataId (
- IN REDFISH_PAYLOAD *Payload
+ IN REDFISH_PAYLOAD *Payload
)
{
- EDKII_JSON_VALUE *JsonValue;
- EDKII_JSON_VALUE *OdataId;
- EFI_STRING OdataIdString;
+ EDKII_JSON_VALUE *JsonValue;
+ EDKII_JSON_VALUE *OdataId;
+ EFI_STRING OdataIdString;
if (Payload == NULL) {
return NULL;
@@ -2117,7 +2159,6 @@ GetOdataId (
return AllocateCopyPool (StrSize (OdataIdString), OdataIdString);
}
-
/**
Get the property name by given Configure Langauge.
@@ -2131,25 +2172,27 @@ GetOdataId (
**/
EFI_STRING
GetPropertyFromConfigureLang (
- IN EFI_STRING ResourceUri,
- IN EFI_STRING ConfigureLang
+ IN EFI_STRING ResourceUri,
+ IN EFI_STRING ConfigureLang
)
{
EFI_STATUS Status;
EFI_STRING TempString;
- if (ConfigureLang == NULL || ResourceUri == NULL) {
+ if ((ConfigureLang == NULL) || (ResourceUri == NULL)) {
return NULL;
}
Status = IsRedpathArray (ConfigureLang, NULL, &TempString);
- if (!EFI_ERROR(Status)) {
+ if (!EFI_ERROR (Status)) {
TempString += 2; // Advance two characters for '}' and '/'
return TempString;
}
+
if (Status != EFI_NOT_FOUND) {
return NULL;
}
+
//
// The ConigLang has no '{}'
//
@@ -2160,6 +2203,7 @@ GetPropertyFromConfigureLang (
if (GetRedpathNodeByIndex (ConfigureLang, 0, &TempString) == NULL) {
return NULL;
}
+
//
// Advance two characters to the starting
// pointer of next node.
@@ -2182,17 +2226,17 @@ GetPropertyFromConfigureLang (
**/
CHAR8 *
GetPropertyStringValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- CHAR8 *AsciiStringValue;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ CHAR8 *AsciiStringValue;
if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
return NULL;
@@ -2201,7 +2245,7 @@ GetPropertyStringValue (
//
// Configure Language buffer.
//
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
ConfigureLangBuffer = AllocatePool (BufferSize);
if (ConfigureLangBuffer == NULL) {
return NULL;
@@ -2240,17 +2284,17 @@ GetPropertyStringValue (
**/
INT64 *
GetPropertyNumericValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- INT64 *ResultValue;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ INT64 *ResultValue;
if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
return NULL;
@@ -2259,7 +2303,7 @@ GetPropertyNumericValue (
//
// Configure Language buffer.
//
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
ConfigureLangBuffer = AllocatePool (BufferSize);
if (ConfigureLangBuffer == NULL) {
return NULL;
@@ -2302,17 +2346,17 @@ GetPropertyNumericValue (
**/
BOOLEAN *
GetPropertyBooleanValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- BOOLEAN *ResultValue;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ BOOLEAN *ResultValue;
if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
return NULL;
@@ -2321,7 +2365,7 @@ GetPropertyBooleanValue (
//
// Configure Language buffer.
//
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
ConfigureLangBuffer = AllocatePool (BufferSize);
if (ConfigureLangBuffer == NULL) {
return NULL;
@@ -2366,8 +2410,8 @@ GetAttributeNameFromConfigLanguage (
IN EFI_STRING ConfigureLanguage
)
{
- UINTN StringLen;
- UINTN Index;
+ UINTN StringLen;
+ UINTN Index;
if (IS_EMPTY_STRING (ConfigureLanguage)) {
return NULL;
@@ -2398,21 +2442,21 @@ GetAttributeNameFromConfigLanguage (
**/
CHAR8 **
GetPropertyStringArrayValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINTN *ArraySize
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- CHAR8 **StringArray;
- UINTN Index;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ CHAR8 **StringArray;
+ UINTN Index;
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| (ArraySize == NULL)) {
return NULL;
}
@@ -2421,7 +2465,7 @@ GetPropertyStringArrayValue (
//
// Configure Language buffer.
//
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
ConfigureLangBuffer = AllocatePool (BufferSize);
if (ConfigureLangBuffer == NULL) {
DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
@@ -2469,21 +2513,21 @@ GetPropertyStringArrayValue (
**/
INT64 *
GetPropertyNumericArrayValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINTN *ArraySize
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- INT64 *IntegerArray;
- UINTN Index;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ INT64 *IntegerArray;
+ UINTN Index;
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| (ArraySize == NULL)) {
return NULL;
}
@@ -2492,7 +2536,7 @@ GetPropertyNumericArrayValue (
//
// Configure Language buffer.
//
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
ConfigureLangBuffer = AllocatePool (BufferSize);
if (ConfigureLangBuffer == NULL) {
DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
@@ -2540,21 +2584,21 @@ GetPropertyNumericArrayValue (
**/
BOOLEAN *
GetPropertyBooleanArrayValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINTN *ArraySize
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINTN *ArraySize
)
{
- EFI_STATUS Status;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- UINTN BufferSize;
- BOOLEAN *BooleanArray;
- UINTN Index;
+ EFI_STATUS Status;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ UINTN BufferSize;
+ BOOLEAN *BooleanArray;
+ UINTN Index;
- if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| ArraySize == NULL) {
+ if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)
|| (ArraySize == NULL)) {
return NULL;
}
@@ -2563,7 +2607,7 @@ GetPropertyBooleanArrayValue (
//
// Configure Language buffer.
//
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
ConfigureLangBuffer = AllocatePool (BufferSize);
if (ConfigureLangBuffer == NULL) {
DEBUG ((DEBUG_ERROR, "%a, out of resource\n", __FUNCTION__));
@@ -2605,25 +2649,28 @@ GetPropertyBooleanArrayValue (
**/
VOID
FreeEmptyPropKeyValueList (
- RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueListHead
)
{
- RedfishCS_EmptyProp_KeyValue *NextEmptyPropKeyValueList;
+ RedfishCS_EmptyProp_KeyValue *NextEmptyPropKeyValueList;
while (EmptyPropKeyValueListHead != NULL) {
NextEmptyPropKeyValueList = EmptyPropKeyValueListHead-NextKeyValuePtr;if (EmptyPropKeyValueListHead->Value->DataValue.CharPtr != NULL) {
- FreePool(EmptyPropKeyValueListHead->Value->DataValue.CharPtr);
+ FreePool (EmptyPropKeyValueListHead->Value->DataValue.CharPtr);
}
+
if (EmptyPropKeyValueListHead->Value != NULL) {
- FreePool(EmptyPropKeyValueListHead->Value);
+ FreePool (EmptyPropKeyValueListHead->Value);
}
+
if (EmptyPropKeyValueListHead->KeyNamePtr != NULL) {
- FreePool(EmptyPropKeyValueListHead->KeyNamePtr);
+ FreePool (EmptyPropKeyValueListHead->KeyNamePtr);
}
+
FreePool (EmptyPropKeyValueListHead);
EmptyPropKeyValueListHead = NextEmptyPropKeyValueList;
- };
+ }
}
/**
@@ -2640,26 +2687,28 @@ FreeEmptyPropKeyValueList (
RedfishCS_EmptyProp_KeyValue *
NewEmptyPropKeyValueFromRedfishValue (
IN EFI_STRING KeyName,
- IN EDKII_REDFISH_VALUE *RedfishValue
+ IN EDKII_REDFISH_VALUE *RedfishValue
)
{
- RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValue;
- RedfishCS_Vague *VagueValue;
- RedfishCS_char *KeyNameChar;
- VOID *Data;
- UINTN DataSize;
- INT32 Bool32;
-
- KeyNameChar = StrUnicodeToAscii(KeyName);
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValue;
+ RedfishCS_Vague *VagueValue;
+ RedfishCS_char *KeyNameChar;
+ VOID *Data;
+ UINTN DataSize;
+ INT32 Bool32;
+
+ KeyNameChar = StrUnicodeToAscii (KeyName);
if (KeyNameChar == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Failed to convert unicode to ASCII.\n",
__FUNCTION__));
return NULL;
}
+
EmptyPropKeyValue = (RedfishCS_EmptyProp_KeyValue
*)AllocateZeroPool (sizeof (RedfishCS_EmptyProp_KeyValue));
if (EmptyPropKeyValue == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
EmptyPropKeyValue\n", __FUNCTION__));
return NULL;
}
+
VagueValue = (RedfishCS_Vague *)AllocateZeroPool (sizeof
(RedfishCS_Vague));
if (VagueValue == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
VagueValue\n", __FUNCTION__));
@@ -2669,29 +2718,30 @@ NewEmptyPropKeyValueFromRedfishValue (
if (RedfishValue->Type == REDFISH_VALUE_TYPE_BOOLEAN) {
VagueValue->DataType = RedfishCS_Vague_DataType_Bool;
- DataSize = sizeof (BOOLEAN);
+ DataSize = sizeof (BOOLEAN);
//
// Redfish JSON to C strcuture converter uses
// "int" for the BOOLEAN.
//
Bool32 = (INT32)RedfishValue->Value.Boolean;
- Data = (VOID *)&Bool32;
+ Data = (VOID *)&Bool32;
} else if (RedfishValue->Type == REDFISH_VALUE_TYPE_INTEGER) {
VagueValue->DataType = RedfishCS_Vague_DataType_Int64;
- DataSize = sizeof (INT64);
- Data = (VOID *)&RedfishValue->Value.Integer;
+ DataSize = sizeof (INT64);
+ Data = (VOID *)&RedfishValue->Value.Integer;
} else if (RedfishValue->Type == REDFISH_VALUE_TYPE_STRING) {
VagueValue->DataType = RedfishCS_Vague_DataType_String;
- DataSize = AsciiStrSize(RedfishValue->Value.Buffer);
- Data = (VOID *)RedfishValue->Value.Buffer;
+ DataSize = AsciiStrSize (RedfishValue->Value.Buffer);
+ Data = (VOID *)RedfishValue->Value.Buffer;
} else {
DEBUG ((DEBUG_ERROR, "%a, wrong type of RedfishValue: %x\n",
__FUNCTION__, RedfishValue->Type));
FreePool (VagueValue);
FreePool (EmptyPropKeyValue);
return NULL;
}
- VagueValue->DataValue.CharPtr = (RedfishCS_char
*)AllocateCopyPool(DataSize, Data);
- EmptyPropKeyValue->Value = VagueValue;
+
+ VagueValue->DataValue.CharPtr = (RedfishCS_char *)AllocateCopyPool
(DataSize, Data);
+ EmptyPropKeyValue->Value = VagueValue;
EmptyPropKeyValue->KeyNamePtr = KeyNameChar;
return EmptyPropKeyValue;
}
@@ -2712,25 +2762,25 @@ NewEmptyPropKeyValueFromRedfishValue (
**/
RedfishCS_EmptyProp_KeyValue *
GetPropertyVagueValue (
- IN CHAR8 *Schema,
- IN CHAR8 *Version,
- IN EFI_STRING PropertyName,
- IN EFI_STRING ConfigureLang,
- OUT UINT32 *NumberOfValues
+ IN CHAR8 *Schema,
+ IN CHAR8 *Version,
+ IN EFI_STRING PropertyName,
+ IN EFI_STRING ConfigureLang,
+ OUT UINT32 *NumberOfValues
)
{
- EFI_STATUS Status;
- RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueList;
- RedfishCS_EmptyProp_KeyValue *PreEmptyPropKeyValueList;
- RedfishCS_EmptyProp_KeyValue *FirstEmptyPropKeyValueList;
- EDKII_REDFISH_VALUE RedfishValue;
- EFI_STRING ConfigureLangBuffer;
- EFI_STRING KeyName;
- EFI_STRING *ConfigureLangList;
- EFI_STRING SearchPattern;
- UINTN BufferSize;
- UINTN ConfigListCount;
- UINTN ConfigListCountIndex;
+ EFI_STATUS Status;
+ RedfishCS_EmptyProp_KeyValue *EmptyPropKeyValueList;
+ RedfishCS_EmptyProp_KeyValue *PreEmptyPropKeyValueList;
+ RedfishCS_EmptyProp_KeyValue *FirstEmptyPropKeyValueList;
+ EDKII_REDFISH_VALUE RedfishValue;
+ EFI_STRING ConfigureLangBuffer;
+ EFI_STRING KeyName;
+ EFI_STRING *ConfigureLangList;
+ EFI_STRING SearchPattern;
+ UINTN BufferSize;
+ UINTN ConfigListCount;
+ UINTN ConfigListCountIndex;
if (IS_EMPTY_STRING (Schema) || IS_EMPTY_STRING (Version) ||
IS_EMPTY_STRING (ConfigureLang) || IS_EMPTY_STRING (PropertyName)) {
return NULL;
@@ -2739,24 +2789,26 @@ GetPropertyVagueValue (
//
// Configure Language buffer.
//
- BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
+ BufferSize = sizeof (CHAR16) * MAX_CONF_LANG_LEN;
ConfigureLangBuffer = AllocatePool (BufferSize);
if (ConfigureLangBuffer == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
ConfigureLangBuffer\n", __FUNCTION__));
return NULL;
}
+
UnicodeSPrint (ConfigureLangBuffer, BufferSize, L"%s/%s", ConfigureLang,
PropertyName);
//
// Initial search pattern
//
- BufferSize = (StrLen (ConfigureLangBuffer) + StrLen (L"/.*") + 1) * sizeof
(CHAR16); // Increase one for the NULL terminator.
+ BufferSize = (StrLen (ConfigureLangBuffer) + StrLen (L"/.*") + 1) * sizeof
(CHAR16); // Increase one for the NULL terminator.
SearchPattern = AllocatePool (BufferSize);
if (SearchPattern == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Failed to allocate memory for
SearchPattern\n", __FUNCTION__));
FreePool (ConfigureLangBuffer);
return NULL;
}
+
BufferSize = BufferSize / sizeof (CHAR16);
StrCpyS (SearchPattern, BufferSize, ConfigureLangBuffer);
StrCatS (SearchPattern, BufferSize, L"/.*");
@@ -2769,28 +2821,30 @@ GetPropertyVagueValue (
//
// Build up the list of RedfishCS_EmptyProp_KeyValue.
//
- ConfigListCountIndex = 0;
- PreEmptyPropKeyValueList = NULL;
+ ConfigListCountIndex = 0;
+ PreEmptyPropKeyValueList = NULL;
FirstEmptyPropKeyValueList = NULL;
while (ConfigListCountIndex < ConfigListCount) {
- Status = RedfishPlatformConfigGetValue(Schema, Version,
ConfigureLangList [ConfigListCountIndex], &RedfishValue);
+ Status = RedfishPlatformConfigGetValue (Schema, Version,
ConfigureLangList[ConfigListCountIndex], &RedfishValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version, ConfigureLangList
[ConfigListCountIndex], Status));
+ DEBUG ((DEBUG_ERROR, "%a, %a.%a query current setting for %s failed:
%r\n", __FUNCTION__, Schema, Version,
ConfigureLangList[ConfigListCountIndex], Status));
goto ErrorLeave;
}
+
//
// Get the key name.
//
- KeyName = GetAttributeNameFromConfigLanguage (ConfigureLangList
[ConfigListCountIndex]);
+ KeyName = GetAttributeNameFromConfigLanguage
(ConfigureLangList[ConfigListCountIndex]);
//
// Create an entry of RedfishCS_EmptyProp_KeyValue.
//
EmptyPropKeyValueList = NewEmptyPropKeyValueFromRedfishValue
(KeyName, &RedfishValue);
if (EmptyPropKeyValueList == NULL) {
DEBUG ((DEBUG_ERROR, "%a, Failed to create an entry of
EmptyPropKeyValueList\n", __FUNCTION__));
- ConfigListCountIndex ++;
+ ConfigListCountIndex++;
continue;
}
+
//
// Link the RedfishCS_EmptyProp_KeyValue list.
//
@@ -2799,24 +2853,29 @@ GetPropertyVagueValue (
} else {
FirstEmptyPropKeyValueList = EmptyPropKeyValueList;
}
+
PreEmptyPropKeyValueList = EmptyPropKeyValueList;
- ConfigListCountIndex ++;
- };
+ ConfigListCountIndex++;
+ }
+
goto LeaveFunction;
ErrorLeave:;
if (FirstEmptyPropKeyValueList != NULL) {
FreeEmptyPropKeyValueList (FirstEmptyPropKeyValueList);
}
+
FirstEmptyPropKeyValueList = NULL;
LeaveFunction:
if (SearchPattern != NULL) {
FreePool (SearchPattern);
}
+
if (ConfigureLangBuffer != NULL) {
FreePool (ConfigureLangBuffer);
}
+
FreePool (ConfigureLangList);
*NumberOfValues = (UINT32)ConfigListCount;
@@ -2836,15 +2895,15 @@ LeaveFunction:
**/
BOOLEAN
PropertyChecker (
- IN VOID *PropertyBuffer,
- IN BOOLEAN ProvisionMode
+ IN VOID *PropertyBuffer,
+ IN BOOLEAN ProvisionMode
)
{
if (ProvisionMode) {
return TRUE;
}
- if (!ProvisionMode && PropertyBuffer != NULL) {
+ if (!ProvisionMode && (PropertyBuffer != NULL)) {
return TRUE;
}
@@ -2865,12 +2924,12 @@ PropertyChecker (
**/
BOOLEAN
CheckEtag (
- IN EFI_STRING Uri,
- IN CHAR8 *EtagInHeader,
- IN CHAR8 *EtagInJson
+ IN EFI_STRING Uri,
+ IN CHAR8 *EtagInHeader,
+ IN CHAR8 *EtagInJson
)
{
- CHAR8 *EtagInDb;
+ CHAR8 *EtagInDb;
if (IS_EMPTY_STRING (Uri)) {
return FALSE;
@@ -2920,15 +2979,15 @@ CheckEtag (
**/
EDKII_JSON_VALUE *
MatchJsonObject (
- IN EDKII_JSON_VALUE *JsonObj,
- IN CHAR8 *ObjectName
+ IN EDKII_JSON_VALUE *JsonObj,
+ IN CHAR8 *ObjectName
)
{
EDKII_JSON_VALUE N;
CHAR8 *Key;
EDKII_JSON_VALUE Value;
- if (JsonObj == NULL || IS_EMPTY_STRING (ObjectName)) {
+ if ((JsonObj == NULL) || IS_EMPTY_STRING (ObjectName)) {
return NULL;
}
@@ -2962,11 +3021,11 @@ MatchPropertyWithJsonContext (
IN CHAR8 *Json
)
{
- CHAR8 *AsciiProperty;
- CHAR8 *PropertyNode;
- UINTN Index;
- EDKII_JSON_VALUE *JsonObj;
- EDKII_JSON_VALUE *MatchObj;
+ CHAR8 *AsciiProperty;
+ CHAR8 *PropertyNode;
+ UINTN Index;
+ EDKII_JSON_VALUE *JsonObj;
+ EDKII_JSON_VALUE *MatchObj;
EDKII_JSON_TYPE JsonType;
if (IS_EMPTY_STRING (Property) || IS_EMPTY_STRING (Json)) {
@@ -2974,7 +3033,7 @@ MatchPropertyWithJsonContext (
}
JsonObj = JsonLoadString (Json, 0, NULL);
- if (JsonObj == NULL || !JsonValueIsObject (JsonObj)) {
+ if ((JsonObj == NULL) || !JsonValueIsObject (JsonObj)) {
return FALSE;
}
@@ -2983,18 +3042,17 @@ MatchPropertyWithJsonContext (
return FALSE;
}
- Index = 0;
+ Index = 0;
PropertyNode = AsciiProperty;
- MatchObj = JsonObj;
+ MatchObj = JsonObj;
//
// Walk through property and find corresponding object in JSON input
//
while (AsciiProperty[Index] != '\0') {
-
if (AsciiProperty[Index] == '/') {
AsciiProperty[Index] = '\0';
- MatchObj = MatchJsonObject (MatchObj, PropertyNode);
+ MatchObj = MatchJsonObject (MatchObj, PropertyNode);
if (MatchObj == NULL) {
PropertyNode = NULL;
break;
@@ -3023,16 +3081,19 @@ MatchPropertyWithJsonContext (
if (JsonValueIsNull (MatchObj)) {
MatchObj = NULL;
}
+
break;
case EdkiiJsonTypeArray:
if (JsonArrayCount (MatchObj) == 0) {
MatchObj = NULL;
}
+
break;
case EdkiiJsonTypeString:
if (IS_EMPTY_STRING (JsonValueGetString (MatchObj))) {
MatchObj = NULL;
}
+
break;
case EdkiiJsonTypeNull:
MatchObj = NULL;
@@ -3061,16 +3122,16 @@ MatchPropertyWithJsonContext (
**/
EFI_STATUS
AddRedfishCharArray (
- IN OUT RedfishCS_char_Array **Head,
+ IN OUT RedfishCS_char_Array **Head,
IN CHAR8 **StringArray,
IN UINTN ArraySize
)
{
- UINTN Index;
- RedfishCS_char_Array *CharArrayBuffer;
- RedfishCS_char_Array *PreArrayBuffer;
+ UINTN Index;
+ RedfishCS_char_Array *CharArrayBuffer;
+ RedfishCS_char_Array *PreArrayBuffer;
- if (Head == NULL || StringArray == NULL || ArraySize == 0) {
+ if ((Head == NULL) || (StringArray == NULL) || (ArraySize == 0)) {
return EFI_INVALID_PARAMETER;
}
@@ -3083,14 +3144,15 @@ AddRedfishCharArray (
}
if (Index == 0) {
- *Head = CharArrayBuffer;
+ *Head = CharArrayBuffer;
}
CharArrayBuffer->ArrayValue = StringArray[Index];
- CharArrayBuffer->Next = NULL;
+ CharArrayBuffer->Next = NULL;
if (PreArrayBuffer != NULL) {
PreArrayBuffer->Next = CharArrayBuffer;
}
+
PreArrayBuffer = CharArrayBuffer;
}
@@ -3111,16 +3173,16 @@ AddRedfishCharArray (
**/
EFI_STATUS
AddRedfishNumericArray (
- IN OUT RedfishCS_int64_Array **Head,
- IN INT64 *NumericArray,
- IN UINTN ArraySize
+ IN OUT RedfishCS_int64_Array **Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
)
{
- UINTN Index;
- RedfishCS_int64_Array *NumericArrayBuffer;
- RedfishCS_int64_Array *PreArrayBuffer;
+ UINTN Index;
+ RedfishCS_int64_Array *NumericArrayBuffer;
+ RedfishCS_int64_Array *PreArrayBuffer;
- if (Head == NULL || NumericArray == NULL || ArraySize == 0) {
+ if ((Head == NULL) || (NumericArray == NULL) || (ArraySize == 0)) {
return EFI_INVALID_PARAMETER;
}
@@ -3133,18 +3195,21 @@ AddRedfishNumericArray (
}
if (Index == 0) {
- *Head = NumericArrayBuffer;
+ *Head = NumericArrayBuffer;
}
+
NumericArrayBuffer->ArrayValue = AllocatePool (sizeof
(RedfishCS_int64));
if (NumericArrayBuffer->ArrayValue == NULL) {
ASSERT (NumericArrayBuffer->ArrayValue != NULL);
continue;
}
+
*NumericArrayBuffer->ArrayValue = NumericArray[Index];
- NumericArrayBuffer->Next = NULL;
+ NumericArrayBuffer->Next = NULL;
if (PreArrayBuffer != NULL) {
PreArrayBuffer->Next = NumericArrayBuffer;
}
+
PreArrayBuffer = NumericArrayBuffer;
}
@@ -3170,11 +3235,11 @@ AddRedfishBooleanArray (
IN UINTN ArraySize
)
{
- UINTN Index;
- RedfishCS_bool_Array *BooleanArrayBuffer;
- RedfishCS_bool_Array *PreArrayBuffer;
+ UINTN Index;
+ RedfishCS_bool_Array *BooleanArrayBuffer;
+ RedfishCS_bool_Array *PreArrayBuffer;
- if (Head == NULL || BooleanArray == NULL || ArraySize == 0) {
+ if ((Head == NULL) || (BooleanArray == NULL) || (ArraySize == 0)) {
return EFI_INVALID_PARAMETER;
}
@@ -3187,7 +3252,7 @@ AddRedfishBooleanArray (
}
if (Index == 0) {
- *Head = BooleanArrayBuffer;
+ *Head = BooleanArrayBuffer;
}
BooleanArrayBuffer->ArrayValue = AllocatePool (sizeof (RedfishCS_bool));
@@ -3195,11 +3260,13 @@ AddRedfishBooleanArray (
ASSERT (BooleanArrayBuffer->ArrayValue != NULL);
continue;
}
+
*BooleanArrayBuffer->ArrayValue = BooleanArray[Index];
- BooleanArrayBuffer->Next = NULL;
+ BooleanArrayBuffer->Next = NULL;
if (PreArrayBuffer != NULL) {
PreArrayBuffer->Next = BooleanArrayBuffer;
}
+
PreArrayBuffer = BooleanArrayBuffer;
}
@@ -3222,22 +3289,21 @@ AddRedfishBooleanArray (
**/
BOOLEAN
CompareRedfishStringArrayValues (
- IN RedfishCS_char_Array *Head,
- IN CHAR8 **StringArray,
- IN UINTN ArraySize
+ IN RedfishCS_char_Array *Head,
+ IN CHAR8 **StringArray,
+ IN UINTN ArraySize
)
{
UINTN Index;
RedfishCS_char_Array *CharArrayBuffer;
- if (Head == NULL || StringArray == NULL || ArraySize == 0) {
+ if ((Head == NULL) || (StringArray == NULL) || (ArraySize == 0)) {
return FALSE;
}
CharArrayBuffer = Head;
- Index = 0;
+ Index = 0;
while (CharArrayBuffer != NULL && Index < ArraySize) {
-
if (AsciiStrCmp (StringArray[Index], CharArrayBuffer->ArrayValue) != 0) {
break;
}
@@ -3246,7 +3312,7 @@ CompareRedfishStringArrayValues (
CharArrayBuffer = CharArrayBuffer->Next;
}
- if (CharArrayBuffer != NULL || Index < ArraySize) {
+ if ((CharArrayBuffer != NULL) || (Index < ArraySize)) {
return FALSE;
}
@@ -3269,20 +3335,20 @@ CompareRedfishStringArrayValues (
**/
BOOLEAN
CompareRedfishNumericArrayValues (
- IN RedfishCS_int64_Array *Head,
- IN INT64 *NumericArray,
- IN UINTN ArraySize
+ IN RedfishCS_int64_Array *Head,
+ IN INT64 *NumericArray,
+ IN UINTN ArraySize
)
{
UINTN Index;
RedfishCS_int64_Array *NumericArrayBuffer;
- if (Head == NULL || NumericArray == NULL || ArraySize == 0) {
+ if ((Head == NULL) || (NumericArray == NULL) || (ArraySize == 0)) {
return FALSE;
}
NumericArrayBuffer = Head;
- Index = 0;
+ Index = 0;
while (NumericArrayBuffer != NULL && Index < ArraySize) {
if (NumericArray[Index] != *NumericArrayBuffer->ArrayValue) {
break;
@@ -3292,7 +3358,7 @@ CompareRedfishNumericArrayValues (
NumericArrayBuffer = NumericArrayBuffer->Next;
}
- if (NumericArrayBuffer != NULL || Index < ArraySize) {
+ if ((NumericArrayBuffer != NULL) || (Index < ArraySize)) {
return FALSE;
}
@@ -3320,15 +3386,15 @@ CompareRedfishBooleanArrayValues (
IN UINTN ArraySize
)
{
- UINTN Index;
+ UINTN Index;
RedfishCS_bool_Array *BooleanArrayBuffer;
- if (Head == NULL || BooleanArray == NULL || ArraySize == 0) {
+ if ((Head == NULL) || (BooleanArray == NULL) || (ArraySize == 0)) {
return FALSE;
}
BooleanArrayBuffer = Head;
- Index = 0;
+ Index = 0;
while (BooleanArrayBuffer != NULL && Index < ArraySize) {
if (BooleanArray[Index] != *BooleanArrayBuffer->ArrayValue) {
break;
@@ -3338,13 +3404,79 @@ CompareRedfishBooleanArrayValues (
BooleanArrayBuffer = BooleanArrayBuffer->Next;
}
- if (BooleanArrayBuffer != NULL || Index < ArraySize) {
+ if ((BooleanArrayBuffer != NULL) || (Index < ArraySize)) {
return FALSE;
}
return TRUE;
}
+/**
+
+ Check and see if "@Redfish.Settings" exist in given Payload. If found,
return the
+ payload and URI to pending settings. Caller has to release "SettingPayload"
and
+ "SettingUri".
+
You missed one parameter for RedfishService.
Thanks.
Abner
+ @param[in] Payload Payload that may contain "@Redfish.Settings"
+ @param[out] SettingPayload Payload keeps pending settings.
+ @param[out] SettingUri URI to pending settings.
+
+ @retval EFI_SUCCESS Pending settings is found and returned.
+ @retval Others Error happens
+
+**/
+EFI_STATUS
+GetPendingSettings (
+ IN REDFISH_SERVICE RedfishService,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *SettingResponse,
+ OUT EFI_STRING *SettingUri
+ )
+{
+ CONST CHAR8 *RedfishSettingsUriKeys[] = { "@Redfish.Settings",
"SettingsObject", "@odata.id" };
+ EDKII_JSON_VALUE JsonValue;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ if ((RedfishService == NULL) || (Payload == NULL) || (SettingResponse ==
NULL) || (SettingUri == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *SettingUri = NULL;
+ JsonValue = RedfishJsonInPayload (Payload);
+
+ //
+ // Seeking RedfishSettings URI link.
+ //
+ for (Index = 0; Index < ARRAY_SIZE (RedfishSettingsUriKeys); Index++) {
+ if (JsonValue == NULL) {
+ break;
+ }
+
+ JsonValue = JsonObjectGetValue (JsonValueGetObject (JsonValue),
RedfishSettingsUriKeys[Index]);
+ }
+
+ if (JsonValue != NULL) {
+ //
+ // Verify RedfishSettings URI link is valid to retrieve resource or not.
+ //
+ *SettingUri = JsonValueGetUnicodeString (JsonValue);
+ if (*SettingUri == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Status = GetResourceByUri (RedfishService, *SettingUri,
SettingResponse);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: @Redfish.Settings exists, get resource
from: %s failed: %r\n", __FUNCTION__, *SettingUri, Status));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
/**
Check and see if any difference between two vague value set.
@@ -3361,12 +3493,12 @@ CompareRedfishBooleanArrayValues (
**/
BOOLEAN
CompareRedfishPropertyVagueValues (
- IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
- IN UINT32 RedfishVagueKeyValueNumber,
- IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
- IN UINT32 ConfigVagueKeyValueNumber
+ IN RedfishCS_EmptyProp_KeyValue *RedfishVagueKeyValuePtr,
+ IN UINT32 RedfishVagueKeyValueNumber,
+ IN RedfishCS_EmptyProp_KeyValue *ConfigVagueKeyValuePtr,
+ IN UINT32 ConfigVagueKeyValueNumber
)
- {
+{
RedfishCS_EmptyProp_KeyValue *ThisConfigVagueKeyValuePtr;
RedfishCS_EmptyProp_KeyValue *ThisRedfishVagueKeyValuePtr;
@@ -3384,13 +3516,14 @@ CompareRedfishPropertyVagueValues (
// Loop through all key/value on Redfish service..
//
while (ThisRedfishVagueKeyValuePtr != NULL) {
- if (AsciiStrCmp(ThisConfigVagueKeyValuePtr->KeyNamePtr,
ThisRedfishVagueKeyValuePtr->KeyNamePtr) == 0) {
+ if (AsciiStrCmp (ThisConfigVagueKeyValuePtr->KeyNamePtr,
ThisRedfishVagueKeyValuePtr->KeyNamePtr) == 0) {
//
// Check the type of value.
//
if (ThisConfigVagueKeyValuePtr->Value->DataType !=
ThisRedfishVagueKeyValuePtr->Value->DataType) {
return FALSE;
}
+
//
// Check the value.
//
@@ -3398,11 +3531,13 @@ CompareRedfishPropertyVagueValues (
//
// Is the string identical?
//
- if (AsciiStrCmp (ThisConfigVagueKeyValuePtr->Value-DataValue.CharPtr,- ThisRedfishVagueKeyValuePtr->Value->DataValue.CharPtr
- ) == 0) {
+ if (AsciiStrCmp (
+ ThisConfigVagueKeyValuePtr->Value->DataValue.CharPtr,
+ ThisRedfishVagueKeyValuePtr->Value->DataValue.CharPtr
+ ) == 0)
+ {
break;
- } else{
+ } else {
return FALSE;
}
} else if (ThisConfigVagueKeyValuePtr->Value->DataType ==
RedfishCS_Vague_DataType_Int64) {
@@ -3421,16 +3556,20 @@ CompareRedfishPropertyVagueValues (
return FALSE;
}
}
+
ThisRedfishVagueKeyValuePtr = ThisRedfishVagueKeyValuePtr-NextKeyValuePtr;- };
+ }
+
if (ThisRedfishVagueKeyValuePtr == NULL) {
//
// No matched key name. Threat these two vague value set is different.
//
return FALSE;
}
+
ThisConfigVagueKeyValuePtr = ThisConfigVagueKeyValuePtr-NextKeyValuePtr;- };
+ }
+
return TRUE;
}
@@ -3448,11 +3587,10 @@ CompareRedfishPropertyVagueValues (
EFI_STATUS
EFIAPI
RedfishFeatureUtilityLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
)
{
-
return EFI_SUCCESS;
}
@@ -3468,8 +3606,8 @@ RedfishFeatureUtilityLibConstructor (
EFI_STATUS
EFIAPI
RedfishFeatureUtilityLibDestructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
)
{
return EFI_SUCCESS;
--
2.39.2.windows.1
Re: [PATCH edk2-platforms 1/1] Silicon/RISC-V: Fix a build failure in RiscVCpuLib
Sunil V L
On Tue, Feb 21, 2023 at 09:29:06PM +0800, Chai, Evan wrote:
As we discussed in other thread, please remove the complete module
itself which are available now in edk2, update the DSC/FDF and
send the patch set.
Thanks for doing this cleanup!
Sunil
From: "Chai, Evan" <evan.chai@...>Hi Evan,
RiscVSetSupervisorAddressTranslationRegister() should be moved out from
RiscVCpuLib since it had been merged to MdePkg/Include/Library/BaseLib.h,
to avoid a multiple definition problem in building.
Signed-off-by: Evan Chai <evan.chai@...>
---
As we discussed in other thread, please remove the complete module
itself which are available now in edk2, update the DSC/FDF and
send the patch set.
Thanks for doing this cleanup!
Sunil
Re: [PATCH] UefiCpuPkg: Calculate DisplayFamily correctly
Gerd Hoffmann
On Thu, Mar 02, 2023 at 09:26:49AM +0800, Zhiguang Liu wrote:
take care,
Gerd
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4238Acked-by: Gerd Hoffmann <kraxel@...>
Per SDM, DisplayFamily = Extended_Family_ID + Family_ID.
Correct the related code.
take care,
Gerd
Re: 回复: [edk2-devel] 回复: [edk2-stable202302 PATCH V2 1/1] OvmfPkg/RiscVVirt: Add Stack HOB
Sunil V L
Thank yo very much!, Liming.
toggle quoted message
Show quoted text
On 01/03/23 20:17, gaoliming via groups.io wrote:
Sunil:
PR https://github.com/tianocore/edk2/pull/4084 has been created for this
patch.
Thanks
Liming-----邮件原件-----Has
发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Sunil V L
发送时间: 2023年2月28日 14:47
收件人: devel@edk2.groups.io; gaoliming@...
抄送: 'Andrei Warkentin' <andrei.warkentin@...>; 'Ard Biesheuvel'
<ardb+tianocore@...>; 'Jiewen Yao' <jiewen.yao@...>; 'Jordan
Justen' <jordan.l.justen@...>; 'Gerd Hoffmann' <kraxel@...>;
'Michael D Kinney' <michael.d.kinney@...>; 'Andrew Fish'
<afish@...>; 'Leif Lindholm' <leif@...>
主题: Re: [edk2-devel] 回复: [edk2-stable202302 PATCH V2 1/1]
OvmfPkg/RiscVVirt: Add Stack HOB
On Tue, Feb 28, 2023 at 02:43:13PM +0800, gaoliming via groups.io wrote:Sunil:
Is this a critical issue? Dose this fix need to catch this stable tag?it been verified and code review?Hi Liming,
Yes, this is a critical issue. So, I request to catch the stable tag.
Andrei who reported this issue has verified the fix and helped with
review.
https://edk2.groups.io/g/devel/message/100496
Thanks!
Sunil
[PATCH] IntelSiliconPkg/Vtd: Add Vtd core drivers
Sheng Wei
Add 2 drivers (IntelVTdCorePei, IntelVTdCoreDxe)
for pre-boot DMA protection feature.
Change-Id: I306a10b33a1fc4f80fa63c1fc1fb559aa054aa8c
Signed-off-by: Sheng Wei <w.sheng@...>
Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Jenny Huang <jenny.huang@...>
Cc: Robert Kowalewski <robert.kowalewski@...>
---
.../Feature/VTd/IntelVTdCoreDxe/BmDma.c | 547 +++++
.../VTd/IntelVTdCoreDxe/DmaProtection.c | 703 +++++++
.../VTd/IntelVTdCoreDxe/DmaProtection.h | 658 ++++++
.../VTd/IntelVTdCoreDxe/DmarAcpiTable.c | 398 ++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.c | 782 +++++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.inf | 92 +
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.uni | 14 +
.../IntelVTdCoreDxe/IntelVTdCoreDxeExtra.uni | 14 +
.../Feature/VTd/IntelVTdCoreDxe/PciInfo.c | 419 ++++
.../VTd/IntelVTdCoreDxe/TranslationTable.c | 1112 ++++++++++
.../VTd/IntelVTdCoreDxe/TranslationTableEx.c | 108 +
.../Feature/VTd/IntelVTdCoreDxe/VtdReg.c | 759 +++++++
.../Feature/VTd/IntelVTdCorePei/DmarTable.c | 301 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.c | 1099 ++++++++++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.h | 272 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.inf | 70 +
.../VTd/IntelVTdCorePei/IntelVTdCorePei.uni | 14 +
.../IntelVTdCorePei/IntelVTdCorePeiExtra.uni | 14 +
.../VTd/IntelVTdCorePei/IntelVTdDmar.c | 731 +++++++
.../VTd/IntelVTdCorePei/TranslationTable.c | 926 +++++++++
.../Include/Guid/VtdLogDataHob.h | 151 ++
.../Include/Library/IntelVTdPeiDxeLib.h | 329 +++
.../IntelSiliconPkg/Include/Protocol/VtdLog.h | 59 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 21 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dsc | 1 +
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.c | 1810 +++++++++++++++++
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.inf | 30 +
.../IntelVTdPeiDxeLibExt.inf | 34 +
28 files changed, 11468 insertions(+)
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/BmDma.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmarAcpiTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxeExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/PciInfo.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTableEx.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/VtdReg.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/DmarTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePeiExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdDmar.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHo=
b.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdP=
eiDxeLib.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLibExt.inf
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDm=
a.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
new file mode 100644
index 000000000..41917a004
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
@@ -0,0 +1,547 @@
+/** @file=0D
+ BmDma related function=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+// TBD: May make it a policy=0D
+#define DMA_MEMORY_TOP MAX_UINTN=0D
+//#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL=0D
+=0D
+#define MAP_HANDLE_INFO_SIGNATURE SIGNATURE_32 ('H', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EFI_HANDLE DeviceHandle;=0D
+ UINT64 IoMmuAccess;=0D
+} MAP_HANDLE_INFO;=0D
+#define MAP_HANDLE_INFO_FROM_LINK(a) CR (a, MAP_HANDLE_INFO, Link, MAP_HAN=
DLE_INFO_SIGNATURE)=0D
+=0D
+#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EDKII_IOMMU_OPERATION Operation;=0D
+ UINTN NumberOfBytes;=0D
+ UINTN NumberOfPages;=0D
+ EFI_PHYSICAL_ADDRESS HostAddress;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ LIST_ENTRY HandleList;=0D
+} MAP_INFO;=0D
+#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)=0D
+=0D
+LIST_ENTRY gMaps =3D INITIALIZE_LIST_HEAD_VARIABLE(=
gMaps);=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ //=0D
+ // Find MapInfo according to DeviceAddress=0D
+ //=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo->DeviceAddress =3D=3D DeviceAddress) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapInfo =3D=3D NULL) || (MapInfo->DeviceAddress !=3D DeviceAddress)=
) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: DeviceAddress(0x%lx) =
- not found\n", DeviceAddress));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // Find MapHandleInfo according to DeviceHandle=0D
+ //=0D
+ MapHandleInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&MapInfo->HandleList)=0D
+ ; !IsNull (&MapInfo->HandleList, Link)=0D
+ ; Link =3D GetNextNode (&MapInfo->HandleList, Link)=0D
+ ) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (Link);=0D
+ if (MapHandleInfo->DeviceHandle =3D=3D DeviceHandle) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapHandleInfo !=3D NULL) && (MapHandleInfo->DeviceHandle =3D=3D Dev=
iceHandle)) {=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // No DeviceHandle=0D
+ // Initialize and insert the MAP_HANDLE_INFO structure=0D
+ //=0D
+ MapHandleInfo =3D AllocatePool (sizeof (MAP_HANDLE_INFO));=0D
+ if (MapHandleInfo =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: %r\n", EFI_OUT_OF_RES=
OURCES));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ MapHandleInfo->Signature =3D MAP_HANDLE_INFO_SIGNATURE;=0D
+ MapHandleInfo->DeviceHandle =3D DeviceHandle;=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ InsertTailList (&MapInfo->HandleList, &MapHandleInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+ MAP_INFO *MapInfo;=0D
+ EFI_PHYSICAL_ADDRESS DmaMemoryTop;=0D
+ BOOLEAN NeedRemap;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ if (NumberOfBytes =3D=3D NULL || DeviceAddress =3D=3D NULL ||=0D
+ Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: =3D=3D> 0x%08x - 0x%08x (%x)\n", HostA=
ddress, *NumberOfBytes, Operation));=0D
+=0D
+ //=0D
+ // Make sure that Operation is valid=0D
+ //=0D
+ if ((UINT32) Operation >=3D EdkiiIoMmuOperationMaximum) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ NeedRemap =3D FALSE;=0D
+ PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;=0D
+=0D
+ DmaMemoryTop =3D DMA_MEMORY_TOP;=0D
+=0D
+ //=0D
+ // Alignment check=0D
+ //=0D
+ if ((*NumberOfBytes !=3D ALIGN_VALUE(*NumberOfBytes, SIZE_4KB)) ||=0D
+ (PhysicalAddress !=3D ALIGN_VALUE(PhysicalAddress, SIZE_4KB))) {=0D
+ if ((Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer) ||=0D
+ (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) {=0D
+ //=0D
+ // The input buffer might be a subset from IoMmuAllocateBuffer.=0D
+ // Skip the check.=0D
+ //=0D
+ } else {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+ }=0D
+=0D
+ if ((PhysicalAddress + *NumberOfBytes) >=3D DMA_MEMORY_TOP) {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+=0D
+ if (((Operation !=3D EdkiiIoMmuOperationBusMasterRead64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterWrite64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) &&=0D
+ ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {=0D
+ //=0D
+ // If the root bridge or the device cannot handle performing DMA above=
=0D
+ // 4GB but any part of the DMA transfer being mapped is above 4GB, the=
n=0D
+ // map the DMA transfer to a buffer below 4GB.=0D
+ //=0D
+ NeedRemap =3D TRUE;=0D
+ DmaMemoryTop =3D MIN (DmaMemoryTop, SIZE_4GB - 1);=0D
+ }=0D
+=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64) {=0D
+ if (NeedRemap) {=0D
+ //=0D
+ // Common Buffer operations can not be remapped. If the common buff=
er=0D
+ // is above 4GB, then it is not possible to generate a mapping, so r=
eturn=0D
+ // an error.=0D
+ //=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is=
=0D
+ // called later.=0D
+ //=0D
+ MapInfo =3D AllocatePool (sizeof (MAP_INFO));=0D
+ if (MapInfo =3D=3D NULL) {=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_OUT_OF_RESOURCES));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the MAP_INFO structure=0D
+ //=0D
+ MapInfo->Signature =3D MAP_INFO_SIGNATURE;=0D
+ MapInfo->Operation =3D Operation;=0D
+ MapInfo->NumberOfBytes =3D *NumberOfBytes;=0D
+ MapInfo->NumberOfPages =3D EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes=
);=0D
+ MapInfo->HostAddress =3D PhysicalAddress;=0D
+ MapInfo->DeviceAddress =3D DmaMemoryTop;=0D
+ InitializeListHead(&MapInfo->HandleList);=0D
+=0D
+ //=0D
+ // Allocate a buffer below 4GB to map the transfer to.=0D
+ //=0D
+ if (NeedRemap) {=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ EfiBootServicesData,=0D
+ MapInfo->NumberOfPages,=0D
+ &MapInfo->DeviceAddress=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (MapInfo);=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+=0D
+ //=0D
+ // If this is a read operation from the Bus Master's point of view,=0D
+ // then copy the contents of the real buffer into the mapped buffer=0D
+ // so the Bus Master can read the contents of the real buffer.=0D
+ //=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterRead ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterRead64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+ } else {=0D
+ MapInfo->DeviceAddress =3D MapInfo->HostAddress;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ InsertTailList (&gMaps, &MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // The DeviceAddress is the address of the maped buffer below 4GB=0D
+ //=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ //=0D
+ // Return a pointer to the MAP_INFO structure in Mapping=0D
+ //=0D
+ *Mapping =3D MapInfo;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: 0x%08x - 0x%08x <=3D=3D\n", *DeviceAdd=
ress, *Mapping));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_MAP, (UINT64) (*DeviceAddress), (UINT64=
) Operation);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuUnmap: 0x%08x\n", Mapping));=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ RemoveEntryList (&MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // remove all nodes in MapInfo->HandleList=0D
+ //=0D
+ while (!IsListEmpty (&MapInfo->HandleList)) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (MapInfo->HandleList.Forwa=
rdLink);=0D
+ RemoveEntryList (&MapHandleInfo->Link);=0D
+ FreePool (MapHandleInfo);=0D
+ }=0D
+=0D
+ if (MapInfo->DeviceAddress !=3D MapInfo->HostAddress) {=0D
+ //=0D
+ // If this is a write operation from the Bus Master's point of view,=0D
+ // then copy the contents of the mapped buffer into the real buffer=0D
+ // so the processor can read the contents of the real buffer.=0D
+ //=0D
+ if (MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite ||=0D
+ MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ //=0D
+ // Free the mapped buffer and the MAP_INFO structure.=0D
+ //=0D
+ gBS->FreePages (MapInfo->DeviceAddress, MapInfo->NumberOfPages);=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_UNMAP, MapInfo->NumberOfBytes, MapInfo-=
+ FreePool (Mapping);=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: =3D=3D> 0x%08x\n", Pages));=
=0D
+=0D
+ //=0D
+ // Validate Attributes=0D
+ //=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) !=
=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ //=0D
+ // Check for invalid inputs=0D
+ //=0D
+ if (HostAddress =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ //=0D
+ // The only valid memory types are EfiBootServicesData and=0D
+ // EfiRuntimeServicesData=0D
+ //=0D
+ if (MemoryType !=3D EfiBootServicesData &&=0D
+ MemoryType !=3D EfiRuntimeServicesData) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ PhysicalAddress =3D DMA_MEMORY_TOP;=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) =3D=3D 0) {=
=0D
+ //=0D
+ // Limit allocations to memory below 4GB=0D
+ //=0D
+ PhysicalAddress =3D MIN (PhysicalAddress, SIZE_4GB - 1);=0D
+ }=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ MemoryType,=0D
+ Pages,=0D
+ &PhysicalAddress=0D
+ );=0D
+ if (!EFI_ERROR (Status)) {=0D
+ *HostAddress =3D (VOID *) (UINTN) PhysicalAddress;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_ALLOC_BUFFER, (UINT64) Pages, (UINT64=
) (*HostAddress));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: 0x%08x <=3D=3D\n", *HostAdd=
ress));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuFreeBuffer: 0x%\n", Pages));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_FREE_BUFFER, Pages, (UINT64) HostAddres=
s);=0D
+=0D
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages=
);=0D
+}=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ LIST_ENTRY *Link;=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ *NumberOfPages =3D MapInfo->NumberOfPages;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.c
new file mode 100644
index 000000000..f2debe5a5
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.c
@@ -0,0 +1,703 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+UINT64 mBelow4GMemoryLimit;=0D
+UINT64 mAbove4GMemoryLimit;=0D
+=0D
+EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+VTD_ACCESS_REQUEST *mAccessRequest =3D NULL;=0D
+UINTN mAccessRequestCount =3D 0;=0D
+UINTN mAccessRequestMaxCount =3D 0;=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_ACCESS_REQUEST *NewAccessRequest;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // Optimization for memory.=0D
+ //=0D
+ // If the last record is to IoMmuAccess=3D0,=0D
+ // Check previous records and remove the matched entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ if ((mAccessRequest[Index].Segment =3D=3D Segment) &&=0D
+ (mAccessRequest[Index].SourceId.Uint16 =3D=3D SourceId.Uint16) &=
&=0D
+ (mAccessRequest[Index].BaseAddress =3D=3D BaseAddress) &&=0D
+ (mAccessRequest[Index].Length =3D=3D Length) &&=0D
+ (mAccessRequest[Index].IoMmuAccess !=3D 0)) {=0D
+ //=0D
+ // Remove this record [Index].=0D
+ // No need to add the new record.=0D
+ //=0D
+ if (Index !=3D mAccessRequestCount - 1) {=0D
+ CopyMem (=0D
+ &mAccessRequest[Index],=0D
+ &mAccessRequest[Index + 1],=0D
+ sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index=
)=0D
+ );=0D
+ }=0D
+ ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCE=
SS_REQUEST));=0D
+ mAccessRequestCount--;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequestCount >=3D mAccessRequestMaxCount) {=0D
+ NewAccessRequest =3D AllocateZeroPool (sizeof(*NewAccessRequest) * (mA=
ccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));=0D
+ if (NewAccessRequest =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mAccessRequestMaxCount +=3D MAX_VTD_ACCESS_REQUEST;=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest)=
* mAccessRequestCount);=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NewAccessRequest;=0D
+ }=0D
+=0D
+ ASSERT (mAccessRequestCount < mAccessRequestMaxCount);=0D
+=0D
+ mAccessRequest[mAccessRequestCount].Segment =3D Segment;=0D
+ mAccessRequest[mAccessRequestCount].SourceId =3D SourceId;=0D
+ mAccessRequest[mAccessRequestCount].BaseAddress =3D BaseAddress;=0D
+ mAccessRequest[mAccessRequestCount].Length =3D Length;=0D
+ mAccessRequest[mAccessRequestCount].IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ mAccessRequestCount++;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process Access Requests from before DMAR table is installed.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessRequestedAccessAttribute (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));=0D
+=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "PCI(S%x.B%x.D%x.F%x) ",=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId.Bits.Bus,=0D
+ mAccessRequest[Index].SourceId.Bits.Device,=0D
+ mAccessRequest[Index].SourceId.Bits.Function=0D
+ ));=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "(0x%lx~0x%lx) - %lx\n",=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ ));=0D
+ Status =3D SetAccessAttribute (=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId,=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NULL;=0D
+ mAccessRequestCount =3D 0;=0D
+ mAccessRequestMaxCount =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));=0D
+}=0D
+=0D
+/**=0D
+ Return UEFI memory map information.=0D
+=0D
+ @param[out] Below4GMemoryLimit The below 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+ @param[out] Above4GMemoryLimit The above 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+=0D
+**/=0D
+VOID=0D
+ReturnUefiMemoryMap (=0D
+ OUT UINT64 *Below4GMemoryLimit,=0D
+ OUT UINT64 *Above4GMemoryLimit=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR *NextEfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR TempEfiEntry;=0D
+ UINTN EfiMemoryMapSize;=0D
+ UINTN EfiMapKey;=0D
+ UINTN EfiDescriptorSize;=0D
+ UINT32 EfiDescriptorVersion;=0D
+ UINT64 MemoryBlockLength;=0D
+=0D
+ *Below4GMemoryLimit =3D 0;=0D
+ *Above4GMemoryLimit =3D 0;=0D
+=0D
+ //=0D
+ // Get the EFI memory map.=0D
+ //=0D
+ EfiMemoryMapSize =3D 0;=0D
+ EfiMemoryMap =3D NULL;=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+=0D
+ do {=0D
+ //=0D
+ // Use size returned back plus 1 descriptor for the AllocatePool.=0D
+ // We don't just multiply by 2 since the "for" loop below terminates o=
n=0D
+ // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize=
=0D
+ // we process bogus entries and create bogus E820 entries.=0D
+ //=0D
+ EfiMemoryMap =3D (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapS=
ize);=0D
+ if (EfiMemoryMap =3D=3D NULL) {=0D
+ ASSERT (EfiMemoryMap !=3D NULL);=0D
+ return;=0D
+ }=0D
+=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (EfiMemoryMap);=0D
+ }=0D
+ } while (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Sort memory map from low to high=0D
+ //=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ while (NextEfiEntry < EfiMemoryMapEnd) {=0D
+ if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {=0D
+ CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTO=
R));=0D
+ }=0D
+=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptor=
Size);=0D
+ }=0D
+=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "MemoryMap:\n"));=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ MemoryBlockLength =3D (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12=
));=0D
+ DEBUG ((DEBUG_INFO, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry->T=
ype, EfiEntry->PhysicalStart, EfiEntry->PhysicalStart + MemoryBlockLength))=
;=0D
+ switch (EfiEntry->Type) {=0D
+ case EfiLoaderCode:=0D
+ case EfiLoaderData:=0D
+ case EfiBootServicesCode:=0D
+ case EfiBootServicesData:=0D
+ case EfiConventionalMemory:=0D
+ case EfiRuntimeServicesCode:=0D
+ case EfiRuntimeServicesData:=0D
+ case EfiACPIReclaimMemory:=0D
+ case EfiACPIMemoryNVS:=0D
+ case EfiReservedMemoryType:=0D
+ if ((EfiEntry->PhysicalStart + MemoryBlockLength) <=3D BASE_1MB) {=0D
+ //=0D
+ // Skip the memory block is under 1MB=0D
+ //=0D
+ } else if (EfiEntry->PhysicalStart >=3D BASE_4GB) {=0D
+ if (*Above4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Above4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ } else {=0D
+ if (*Below4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Below4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ }=0D
+ break;=0D
+ }=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);=0D
+ }=0D
+=0D
+ FreePool (EfiMemoryMap);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Result:\n"));=0D
+ DEBUG ((DEBUG_INFO, "Below4GMemoryLimit: 0x%016lx\n", *Below4GMemoryLim=
it));=0D
+ DEBUG ((DEBUG_INFO, "Above4GMemoryLimit: 0x%016lx\n", *Above4GMemoryLim=
it));=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackAlwaysEnablePageAttribute (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ EFI_STATUS Status;=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (Segment, SourceId);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device in the DeviceScope.=
=0D
+=0D
+ @param[in] DeviceScope the input device scope data structure=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device scope.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeDeviceScope (=0D
+ IN EDKII_PLATFORM_VTD_DEVICE_SCOPE *DeviceScope=0D
+ )=0D
+{=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceS=
cope->DeviceScope, &Bus, &Device, &Function);=0D
+=0D
+ if (DeviceScope->DeviceScope.Type =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYP=
E_PCI_BRIDGE) {=0D
+ //=0D
+ // Need scan the bridge and add all devices.=0D
+ //=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Device=
Scope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIS=
TER_OFFSET));=0D
+ Status =3D ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusN=
umber, ScanBusCallbackAlwaysEnablePageAttribute);=0D
+ return Status;=0D
+ } else {=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, Sour=
ceId);=0D
+ return Status;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device matching DeviceId.=0D
+=0D
+ @param[in] PciDeviceId the input PCI device ID=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device matching DeviceId.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributePciDeviceId (=0D
+ IN EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ UINTN PciIndex;=0D
+ PCI_DEVICE_DATA *PciDeviceData;=0D
+ EFI_STATUS Status;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ for (PciIndex =3D 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDevic=
eInfo->PciDeviceDataNumber; PciIndex++) {=0D
+ PciDeviceData =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciD=
eviceData[PciIndex];=0D
+=0D
+ if (((PciDeviceId->VendorId =3D=3D 0xFFFF) || (PciDeviceId->VendorId=
=3D=3D PciDeviceData->PciDeviceId.VendorId)) &&=0D
+ ((PciDeviceId->DeviceId =3D=3D 0xFFFF) || (PciDeviceId->DeviceId=
=3D=3D PciDeviceData->PciDeviceId.DeviceId)) &&=0D
+ ((PciDeviceId->RevisionId =3D=3D 0xFF) || (PciDeviceId->Revision=
Id =3D=3D PciDeviceData->PciDeviceId.RevisionId)) &&=0D
+ ((PciDeviceId->SubsystemVendorId =3D=3D 0xFFFF) || (PciDeviceId-=
+ ((PciDeviceId->SubsystemDeviceId =3D=3D 0xFFFF) || (PciDeviceId-=
+ Status =3D AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex=
].Segment, PciDeviceData->PciSourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ continue;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] DeviceInfo the exception device information=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device info.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeExceptionDeviceInfo (=0D
+ IN EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *DeviceInfo=0D
+ )=0D
+{=0D
+ switch (DeviceInfo->Type) {=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:=0D
+ return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1))=
;=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:=0D
+ return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1))=
;=0D
+ default:=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN DeviceInfoCount;=0D
+ VOID *DeviceInfo;=0D
+ EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // It is optional.=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEdkiiPlatformVTdPolicyProtocolGuid,=0D
+ NULL,=0D
+ (VOID **)&mPlatformVTdPolicy=0D
+ );=0D
+ if (!EFI_ERROR(Status)) {=0D
+ DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));=0D
+ Status =3D mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPol=
icy, &DeviceInfoCount, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ ThisDeviceInfo =3D DeviceInfo;=0D
+ for (Index =3D 0; Index < DeviceInfoCount; Index++) {=0D
+ if (ThisDeviceInfo->Type =3D=3D EDKII_PLATFORM_VTD_EXCEPTION_DEVIC=
E_INFO_TYPE_END) {=0D
+ break;=0D
+ }=0D
+ AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);=0D
+ ThisDeviceInfo =3D (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo=
->Length);=0D
+ }=0D
+ FreePool (DeviceInfo);=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd engine.=0D
+**/=0D
+VOID=0D
+SetupVtd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VOID *PciEnumerationComplete;=0D
+ UINTN Index;=0D
+ UINT64 Below4GMemoryLimit;=0D
+ UINT64 Above4GMemoryLimit;=0D
+ VTD_ROOT_TABLE_INFO RootTableInfo;=0D
+=0D
+ //=0D
+ // PCI Enumeration must be done=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEfiPciEnumerationCompleteProtocolGuid,=0D
+ NULL,=0D
+ &PciEnumerationComplete=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ ReturnUefiMemoryMap (&Below4GMemoryLimit, &Above4GMemoryLimit);=0D
+ Below4GMemoryLimit =3D ALIGN_VALUE_UP(Below4GMemoryLimit, SIZE_256MB);=0D
+ DEBUG ((DEBUG_INFO, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GM=
emoryLimit));=0D
+=0D
+ mBelow4GMemoryLimit =3D Below4GMemoryLimit;=0D
+ mAbove4GMemoryLimit =3D Above4GMemoryLimit;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_SETUP_VTD, Below4GMemoryLimit, Above4GMemoryL=
imit);=0D
+=0D
+ //=0D
+ // 1. setup=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "ParseDmarAcpiTable\n"));=0D
+ Status =3D ParseDmarAcpiTableDrhd ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));=0D
+ PrepareVtdConfig ();=0D
+=0D
+ //=0D
+ // 2. initialization=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));=0D
+ Status =3D SetupTranslationTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ InitializePlatformVTdPolicy ();=0D
+=0D
+ ParseDmarAcpiTableRmrr ();=0D
+=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) =3D=3D 0) {=0D
+ //=0D
+ // Support IOMMU access attribute request recording before DMAR table =
is installed.=0D
+ // Here is to process the requests.=0D
+ //=0D
+ ProcessRequestedAccessAttribute ();=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInf=
ormation[Index].Segment));=0D
+=0D
+ if (mVtdUnitInformation[Index].ExtRootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
Index].ExtRootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 1, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[Index].RootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Ind=
ex].RootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 0, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // 3. enable=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar\n"));=0D
+ Status =3D EnableDmar ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "DumpVtdRegs\n"));=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Notification function of ACPI Table change.=0D
+=0D
+ This is a notification function registered on ACPI Table change event.=0D
+=0D
+ @param Event Event whose notification function is being invoked.=
=0D
+ @param Context Pointer to the notification function's context.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+AcpiNotificationFunc (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetDmarAcpiTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ if (Status =3D=3D EFI_ALREADY_STARTED) {=0D
+ gBS->CloseEvent (Event);=0D
+ }=0D
+ return;=0D
+ }=0D
+ SetupVtd ();=0D
+ gBS->CloseEvent (Event);=0D
+}=0D
+=0D
+/**=0D
+ Exit boot service callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnExitBootServices (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnExitBootServices\n"));=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) {=0D
+ DumpVtdRegsAll ();=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidate all\n"));=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAdd=
ress);=0D
+=0D
+ InvalidateContextCache (VtdIndex);=0D
+=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Legacy boot callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnLegacyBoot (=0D
+ EFI_EVENT Event,=0D
+ VOID *Context=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnLegacyBoot\n"));=0D
+ DumpVtdRegsAll ();=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_EVENT ExitBootServicesEvent;=0D
+ EFI_EVENT LegacyBootEvent;=0D
+ EFI_EVENT EventAcpi10;=0D
+ EFI_EVENT EventAcpi20;=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi10TableGuid,=0D
+ &EventAcpi10=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi20TableGuid,=0D
+ &EventAcpi20=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Signal the events initially for the case=0D
+ // that DMAR table has been installed.=0D
+ //=0D
+ gBS->SignalEvent (EventAcpi20);=0D
+ gBS->SignalEvent (EventAcpi10);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ TPL_CALLBACK,=0D
+ OnExitBootServices,=0D
+ NULL,=0D
+ &gEfiEventExitBootServicesGuid,=0D
+ &ExitBootServicesEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D EfiCreateEventLegacyBootEx (=0D
+ TPL_CALLBACK,=0D
+ OnLegacyBoot,=0D
+ NULL,=0D
+ &LegacyBootEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ return ;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.h
new file mode 100644
index 000000000..5cd59d18e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.h
@@ -0,0 +1,658 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef _DMAR_PROTECTION_H_=0D
+#define _DMAR_PROTECTION_H_=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiDxe.h>=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/PciSegmentLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/UefiLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/PerformanceLib.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/ReportStatusCodeLib.h>=0D
+#include <Library/HobLib.h>=0D
+=0D
+#include <Guid/EventGroup.h>=0D
+#include <Guid/Acpi.h>=0D
+=0D
+#include <Protocol/VtdLog.h>=0D
+#include <Protocol/DxeSmmReadyToLock.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+#include <Protocol/PciIo.h>=0D
+#include <Protocol/PciEnumerationComplete.h>=0D
+#include <Protocol/PlatformVtdPolicy.h>=0D
+#include <Protocol/IoMmu.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+=0D
+#include <IndustryStandard/Pci.h>=0D
+#include <IndustryStandard/DmaRemappingReportingTable.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (=
~((Alignment) - 1)))=0D
+#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))=
=0D
+=0D
+#define VTD_TPL_LEVEL TPL_NOTIFY=0D
+=0D
+//=0D
+// Use 256-bit descriptor=0D
+// Queue size is 128.=0D
+//=0D
+#define VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH 1=0D
+#define VTD_INVALIDATION_QUEUE_SIZE 0=0D
+=0D
+//=0D
+// This is the initial max PCI DATA number.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_PCI_DATA_NUMBER 0x100=0D
+=0D
+typedef struct {=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Segment;=0D
+ VTD_VER_REG VerReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_ROOT_ENTRY *RootEntryTable;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntryTable;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *FixedSecondLevelPagingEntry;=0D
+ BOOLEAN HasDirtyContext;=0D
+ BOOLEAN HasDirtyPages;=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ BOOLEAN Is5LevelPaging;=0D
+ UINT8 EnableQueuedInvalidation;=0D
+ VOID *QiDescBuffer;=0D
+ UINTN QiDescBufferSize;=0D
+} VTD_UNIT_INFORMATION;=0D
+=0D
+//=0D
+// This is the initial max ACCESS request.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_ACCESS_REQUEST 0x100=0D
+=0D
+typedef struct {=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 Length;=0D
+ UINT64 IoMmuAccess;=0D
+} VTD_ACCESS_REQUEST;=0D
+=0D
+=0D
+/**=0D
+ The scan bus callback function.=0D
+=0D
+ It is called in PCI bus scan for each PCI device under the bus.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The specific PCI device is processed in th=
e callback.=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *SCAN_BUS_FUNC_CALLBACK_FUNC) (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+extern EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;=0D
+=0D
+extern UINTN mVtdUnitNumber;=0D
+extern VTD_UNIT_INFORMATION *mVtdUnitInformation;=0D
+=0D
+extern UINT64 mBelow4GMemoryLimit;=0D
+extern UINT64 mAbove4GMemoryLimit;=0D
+=0D
+extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegs (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers for all VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegsAll (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd extended capability registers.=0D
+=0D
+ @param[in] ECapReg The extended capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdECapRegs (=0D
+ IN VTD_ECAP_REG *ECapReg=0D
+ );=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ );=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ );=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR RMRR table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR RMRR table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ );=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ );=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ );=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ );=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dmar=
AcpiTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
rAcpiTable.c
new file mode 100644
index 000000000..21f559983
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmarAcpiTab=
le.c
@@ -0,0 +1,398 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#pragma pack(1)=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT32 Entry;=0D
+} RSDT_TABLE;=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT64 Entry;=0D
+} XSDT_TABLE;=0D
+=0D
+#pragma pack()=0D
+=0D
+EFI_ACPI_DMAR_HEADER *mAcpiDmarTable =3D NULL;=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+**/=0D
+VOID=0D
+VtdDumpDmarTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VtdLibDumpAcpiDmar (NULL, NULL, (EFI_ACPI_DMAR_HEADER *) (UINTN) mAcpiDm=
arTable);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_DMAR_TABLE, mAcpiDmarTable->Header.Length=
, (VOID *)mAcpiDmarTable, mAcpiDmarTable->Header.Length); =0D
+}=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;=0D
+ UINT8 MyBus;=0D
+ UINT8 MyDevice;=0D
+ UINT8 MyFunction;=0D
+=0D
+ DmarPciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)((UINTN)(DmarDevScopeEntry + 1=
));=0D
+ MyBus =3D DmarDevScopeEntry->StartBusNumber;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ while ((UINTN)DmarPciPath + sizeof(EFI_ACPI_DMAR_PCI_PATH) < (UINTN)Dm=
arDevScopeEntry + DmarDevScopeEntry->Length) {=0D
+ MyBus =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, MyBus, M=
yDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=0D
+ DmarPciPath ++;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+ }=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ break;=0D
+ }=0D
+=0D
+ *Bus =3D MyBus;=0D
+ *Device =3D MyDevice;=0D
+ *Function =3D MyFunction;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR DRHD table.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] DmarDrhd The DRHD table.=0D
+=0D
+ @retval EFI_SUCCESS The DRHD table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessDrhd (=0D
+ IN UINTN VtdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D AllocateZeroPool (sizeof=
(PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVICE_DATA) * MAX_VTD_PCI_DATA_NUM=
BER);=0D
+ if (mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D=3D NULL) {=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Segment =3D DmarDrhd->SegmentNu=
mber;=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress =3D (UINTN)DmarDrhd->Re=
gisterBaseAddress;=0D
+ DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, Dma=
rDrhd->RegisterBaseAddress));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->Segment =3D =
DmarDrhd->SegmentNumber;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataMaxNumber =3D =
MAX_VTD_PCI_DATA_NUMBER;=0D
+=0D
+ if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) !=3D 0)=
{=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D TRUE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n"));=0D
+=0D
+ Status =3D ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Sc=
anBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ } else {=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D FALSE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n"));=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarDrhd + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Len=
gth) {=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: "));=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ DEBUG ((DEBUG_INFO,"PCI Endpoint"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ DEBUG ((DEBUG_INFO,"IOAPIC"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ DEBUG ((DEBUG_INFO,"MSI Capable HPET"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));=0D
+ break;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumb=
er, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, DmarDrhd->SegmentNumber, Sourc=
eId, DmarDevScopeEntry->Type, TRUE);=0D
+ if (EFI_ERROR (Status)) {=0D
+ //=0D
+ // There might be duplication for special device other than standard=
PCI device.=0D
+ //=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Dmar=
Drhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIST=
ER_OFFSET));=0D
+ Status =3D ScanPciBus ((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Se=
condaryBusNumber, ScanBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR RMRR table.=0D
+=0D
+ @param[in] DmarRmrr The RMRR table.=0D
+=0D
+ @retval EFI_SUCCESS The RMRR table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessRmrr (=0D
+ IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr-=
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarRmrr + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Len=
gth) {=0D
+ if (DmarDevScopeEntry->Type !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_=
ENDPOINT) {=0D
+ DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%=
x] \n", DmarDevScopeEntry->Type));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->Segment=
Number, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D SetAccessAttribute (=0D
+ DmarRmrr->SegmentNumber,=0D
+ SourceId,=0D
+ DmarRmrr->ReservedMemoryRegionBaseAddress,=0D
+ DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->=
ReservedMemoryRegionBaseAddress,=0D
+ EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Get VTd engine number.=0D
+**/=0D
+UINTN=0D
+GetVtdEngineNumber (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ UINTN VtdIndex;=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdIndex++;=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return VtdIndex ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+ UINTN VtdIndex;=0D
+=0D
+ mVtdUnitNumber =3D GetVtdEngineNumber ();=0D
+ DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));=0D
+ ASSERT (mVtdUnitNumber > 0);=0D
+ if (mVtdUnitNumber =3D=3D 0) {=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ mVtdUnitInformation =3D AllocateZeroPool (sizeof(*mVtdUnitInformation) *=
mVtdUnitNumber);=0D
+ ASSERT (mVtdUnitInformation !=3D NULL);=0D
+ if (mVtdUnitInformation =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ ASSERT (VtdIndex < mVtdUnitNumber);=0D
+ Status =3D ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarH=
eader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ VtdIndex++;=0D
+=0D
+ break;=0D
+=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ ASSERT (VtdIndex =3D=3D mVtdUnitNumber);=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibDumpPciDeviceInfo (NULL, NULL, mVtdUnitInformation[VtdIndex].Pci=
DeviceInfo);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_PCI_DEVICE,=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress,=
=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo,=0D
+ sizeof (PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVI=
CE_DATA) * mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataNumber=
);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_RMRR:=0D
+ Status =3D ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (mAcpiDmarTable !=3D NULL) {=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+=0D
+ mAcpiDmarTable =3D (EFI_ACPI_DMAR_HEADER *) EfiLocateFirstAcpiTable (=0D
+ EFI_ACPI_4_0_DMA_REMAPPING_T=
ABLE_SIGNATURE=0D
+ );=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ return EFI_NOT_FOUND;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));=0D
+ VtdDumpDmarTable();=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/I=
ntelVTdCoreDxe.c
new file mode 100644
index 000000000..dc7a7146d
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.c
@@ -0,0 +1,782 @@
+/** @file=0D
+ Intel VTd driver.=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ );=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ );=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ )=0D
+{=0D
+ EFI_PCI_IO_PROTOCOL *PciIo;=0D
+ UINTN Seg;=0D
+ UINTN Bus;=0D
+ UINTN Dev;=0D
+ UINTN Func;=0D
+ EFI_STATUS Status;=0D
+ EDKII_PLATFORM_VTD_DEVICE_INFO DeviceInfo;=0D
+=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (mPlatformVTdPolicy !=3D NULL) {=0D
+ Status =3D mPlatformVTdPolicy->GetDeviceId (mPlatformVTdPolicy, Device=
Handle, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ *Segment =3D DeviceInfo.Segment;=0D
+ *SourceId =3D DeviceInfo.SourceId;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D gBS->HandleProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (V=
OID **)&PciIo);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ Status =3D PciIo->GetLocation (PciIo, &Seg, &Bus, &Dev, &Func);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ *Segment =3D (UINT16)Seg;=0D
+ SourceId->Bits.Bus =3D (UINT8)Bus;=0D
+ SourceId->Bits.Device =3D (UINT8)Dev;=0D
+ SourceId->Bits.Function =3D (UINT8)Func;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER DeviceAddress is not IoMmu Page size alig=
ned.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VTdSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ CHAR8 PerfToken[sizeof("VTD(S0000.B00.D00.F00)")];=
=0D
+ UINT32 Identifier;=0D
+ VTD_PROTOCOL_SET_ATTRIBUTE LogSetAttribute;=0D
+=0D
+ DumpVtdIfError ();=0D
+=0D
+ Status =3D DeviceHandleToSourceId (DeviceHandle, &Segment, &SourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuSetAttribute: "));=0D
+ DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment, SourceId.Bits.B=
us, SourceId.Bits.Device, SourceId.Bits.Function));=0D
+ DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length, I=
oMmuAccess));=0D
+=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ //=0D
+ // Record the entry to driver global variable.=0D
+ // As such once VTd is activated, the setting can be adopted.=0D
+ //=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) !=3D 0) {=0D
+ //=0D
+ // Force no IOMMU access attribute request recording before DMAR tab=
le is installed.=0D
+ //=0D
+ ASSERT_EFI_ERROR (EFI_NOT_READY);=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ Status =3D RequestAccessAttribute (Segment, SourceId, DeviceAddress, L=
ength, IoMmuAccess);=0D
+ } else {=0D
+ PERF_CODE (=0D
+ AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", S=
egment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_START_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=
=0D
+ );=0D
+=0D
+ Status =3D SetAccessAttribute (Segment, SourceId, DeviceAddress, Lengt=
h, IoMmuAccess);=0D
+=0D
+ PERF_CODE (=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_END_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=0D
+ );=0D
+ }=0D
+=0D
+ if (!EFI_ERROR(Status)) {=0D
+ SyncDeviceHandleToMapInfo (=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ LogSetAttribute.SourceId.Uint16 =3D SourceId.Uint16;=0D
+ LogSetAttribute.DeviceAddress =3D DeviceAddress;=0D
+ LogSetAttribute.Length =3D Length;=0D
+ LogSetAttribute.IoMmuAccess =3D IoMmuAccess;=0D
+ LogSetAttribute.Status =3D Status;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_IOMMU_SET_ATTRIBUTE, 0, &LogSetAttribute,=
sizeof (VTD_PROTOCOL_SET_ATTRIBUTE));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] Mapping The mapping value returned from Map().=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned =
by Map().=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by Mapping.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN VOID *Mapping,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ UINTN NumberOfPages;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+=0D
+ Status =3D GetDeviceInfoFromMapping (Mapping, &DeviceAddress, &NumberOfP=
ages);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ Status =3D VTdSetAttribute (=0D
+ This,=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ EFI_PAGES_TO_SIZE(NumberOfPages),=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+EDKII_IOMMU_PROTOCOL mIntelVTd =3D {=0D
+ EDKII_IOMMU_PROTOCOL_REVISION,=0D
+ IoMmuSetAttribute,=0D
+ IoMmuMap,=0D
+ IoMmuUnmap,=0D
+ IoMmuAllocateBuffer,=0D
+ IoMmuFreeBuffer,=0D
+};=0D
+=0D
+UINT8 *mVtdLogBuffer =3D NULL;=0D
+=0D
+UINT8 *mVtdLogDxeFreeBuffer =3D NULL;=0D
+UINT32 mVtdLogDxeBufferUsed =3D 0;=0D
+=0D
+UINT32 mVtdLogPeiPostMemBufferUsed =3D 0;=0D
+=0D
+UINT8 mVtdLogPeiError =3D 0;=0D
+UINT16 mVtdLogDxeError =3D 0;=0D
+=0D
+/**=0D
+ Allocate memory buffer for VTd log items.=0D
+=0D
+ @param[in] MemorySize Required memory buffer size.=0D
+=0D
+ @retval Buffer address=0D
+=0D
+**/=0D
+UINT8 *=0D
+EFIAPI=0D
+VTdLogAllocMemory (=0D
+ IN CONST UINT32 MemorySize=0D
+ )=0D
+{=0D
+ UINT8 *Buffer;=0D
+=0D
+ Buffer =3D NULL;=0D
+ if (mVtdLogDxeFreeBuffer !=3D NULL) {=0D
+ if ((mVtdLogDxeBufferUsed + MemorySize) <=3D PcdGet32 (PcdVTdDxeLogBuf=
ferSize)) {=0D
+ Buffer =3D mVtdLogDxeFreeBuffer;=0D
+=0D
+ mVtdLogDxeFreeBuffer +=3D MemorySize;=0D
+ mVtdLogDxeBufferUsed +=3D MemorySize;=0D
+ } else {=0D
+ mVtdLogDxeError |=3D VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ }=0D
+ return Buffer;=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM *Item;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ Item =3D (VTDLOG_EVENT_2PARAM *) VTdLogAllocMemory (sizeof (VTDLOG_EVENT=
_2PARAM));=0D
+ if (Item !=3D NULL) {=0D
+ Item->Data1 =3D Data1;=0D
+ Item->Data2 =3D Data2;=0D
+=0D
+ Item->Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_CONTEXT *Item;=0D
+ UINT32 EventSize;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ EventSize =3D sizeof (VTDLOG_EVENT_CONTEXT) + DataSize - 1;=0D
+=0D
+ Item =3D (VTDLOG_EVENT_CONTEXT *) VTdLogAllocMemory (EventSize);=0D
+ if (Item !=3D NULL) {=0D
+ Item->Param =3D Param;=0D
+ CopyMem (Item->Data, Data, DataSize);=0D
+=0D
+ Item->Header.DataSize =3D EventSize;=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+ =0D
+/**=0D
+ Get Event Items From Pei Pre-Mem Buffer=0D
+=0D
+ @param[in] Buffer Pre-Memory data buffer.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log event=
=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromPeiPreMemBuffer (=0D
+ IN VTDLOG_PEI_PRE_MEM_INFO *InfoBuffer,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINT64 EventCount;=0D
+ VTDLOG_EVENT_2PARAM Event;=0D
+=0D
+ if (InfoBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ EventCount =3D 0;=0D
+ for (Index =3D 0; Index < VTD_LOG_PEI_PRE_MEM_BAR_MAX; Index++) {=0D
+ if (InfoBuffer[Index].Mode =3D=3D VTD_LOG_PEI_PRE_MEM_NOT_USED) {=0D
+ continue;=0D
+ }=0D
+ if (CallbackHandle) {=0D
+ Event.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Event.Header.Timestamp =3D 0;=0D
+=0D
+ Event.Header.LogType =3D ((UINT64) 1) << VTDLOG_PEI_PRE_MEM_DMA_PROT=
ECT;=0D
+ Event.Data1 =3D InfoBuffer[Index].BarAddress;=0D
+ Event.Data2 =3D InfoBuffer[Index].Mode;=0D
+ Event.Data2 |=3D InfoBuffer[Index].Status<<8;=0D
+ CallbackHandle (Context, &Event.Header);=0D
+ }=0D
+ EventCount++;=0D
+ }=0D
+=0D
+ return EventCount;=0D
+}=0D
+=0D
+/**=0D
+ Get Event Items From Pei Post-Mem/Dxe Buffer=0D
+=0D
+ @param[in] Buffer Data buffer.=0D
+ @param[in] BufferUsed Data buffer used.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromBuffer (=0D
+ IN UINT8 *Buffer,=0D
+ IN UINT32 BufferUsed,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 Count;=0D
+ VTDLOG_EVENT_HEADER *Header;=0D
+=0D
+ Count =3D 0;=0D
+ if (Buffer !=3D NULL) {=0D
+ while (BufferUsed > 0) {=0D
+ Header =3D (VTDLOG_EVENT_HEADER *) Buffer;=0D
+ if (BufferUsed >=3D Header->DataSize) {=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, Header);=0D
+ }=0D
+ Buffer +=3D Header->DataSize;=0D
+ BufferUsed -=3D Header->DataSize;=0D
+ Count++;=0D
+ } else {=0D
+ BufferUsed =3D 0;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return Count;=0D
+}=0D
+=0D
+/**=0D
+ Generate the VTd log state.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdGenerateStateEvent (=0D
+ IN VTDLOG_EVENT_TYPE EventType,=0D
+ IN UINT64 Data1,=0D
+ IN UINT64 Data2,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM Item;=0D
+=0D
+ Item.Data1 =3D Data1;=0D
+ Item.Data2 =3D Data2;=0D
+=0D
+ Item.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item.Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item.Header.Timestamp =3D 0;=0D
+=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, &Item.Header);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Get the VTd log events.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdLogGetEvents (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 Count;=0D
+ UINT8 *Buffer;=0D
+=0D
+ if (mVtdLogBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ //=0D
+ // PEI pre-memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (=
PcdVTdPeiPostMemLogBufferSize)];=0D
+ Count =3D VTdGetEventItemsFromPeiPreMemBuffer ((VTDLOG_PEI_PRE_MEM_INFO =
*) Buffer, Context, CallbackHandle);=0D
+=0D
+ //=0D
+ // PEI post memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize)];=0D
+ Count +=3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogPeiPostMemBufferUs=
ed, Context, CallbackHandle);=0D
+ if (mVtdLogPeiError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_PEI_BASIC, mVtdLogPeiError, 0, Context, =
CallbackHandle);=0D
+ Count++;=0D
+ }=0D
+=0D
+ //=0D
+ // DXE phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[0];=0D
+ Count +=3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogDxeBufferUsed, Con=
text, CallbackHandle);=0D
+ if (mVtdLogDxeError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_DXE_BASIC, mVtdLogDxeError, 0, Context, =
CallbackHandle);=0D
+ Count++;=0D
+ }=0D
+=0D
+ return Count;=0D
+}=0D
+=0D
+EDKII_VTD_LOG_PROTOCOL mIntelVTdLog =3D {=0D
+ EDKII_VTD_LOG_PROTOCOL_REVISION,=0D
+ VTdLogGetEvents=0D
+};=0D
+=0D
+/**=0D
+ Initializes the VTd Log.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogInitialize(=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINT32 TotalBufferSize;=0D
+ EFI_STATUS Status;=0D
+ VOID *HobPtr;=0D
+ VTDLOG_PEI_BUFFER_HOB *HobPeiBuffer;=0D
+ EFI_HANDLE Handle;=0D
+ UINT32 BufferOffset;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ }=0D
+=0D
+ if (mVtdLogBuffer !=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ TotalBufferSize =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTd=
PeiPostMemLogBufferSize) + sizeof (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_P=
RE_MEM_BAR_MAX;=0D
+=0D
+ Status =3D gBS->AllocatePool (EfiBootServicesData, TotalBufferSize, &mVt=
dLogBuffer);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // DXE Buffer=0D
+ //=0D
+ if (PcdGet32 (PcdVTdDxeLogBufferSize) > 0) {=0D
+ mVtdLogDxeFreeBuffer =3D mVtdLogBuffer;=0D
+ mVtdLogDxeBufferUsed =3D 0;=0D
+ }=0D
+=0D
+ //=0D
+ // Get PEI pre-memory buffer offset=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTdPei=
PostMemLogBufferSize);=0D
+=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ HobPeiBuffer =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ //=0D
+ // Copy PEI pre-memory phase VTd log.=0D
+ //=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], &HobPeiBuffer->PreMemInfo, size=
of (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+=0D
+ //=0D
+ // Copy PEI post-memory pase VTd log.=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize);=0D
+ if (PcdGet32 (PcdVTdPeiPostMemLogBufferSize) > 0) {=0D
+ if (HobPeiBuffer->PostMemBufferUsed > 0) {=0D
+ mVtdLogPeiPostMemBufferUsed =3D HobPeiBuffer->PostMemBufferUsed;=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], (UINT8 *) (UINTN) HobPeiBuf=
fer->PostMemBuffer, mVtdLogPeiPostMemBufferUsed);=0D
+ }=0D
+ }=0D
+=0D
+ mVtdLogPeiError =3D HobPeiBuffer->VtdLogPeiError;=0D
+ } else {=0D
+ //=0D
+ // Do not find PEI Vtd log, clear PEI pre-memory phase buffer.=0D
+ //=0D
+ ZeroMem (&mVtdLogBuffer[BufferOffset], sizeof (VTDLOG_PEI_PRE_MEM_INFO=
) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+ }=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiVTdLogProtocolGuid,=0D
+ &mIntelVTdLog,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+}=0D
+=0D
+/**=0D
+ Initialize the VTd driver.=0D
+=0D
+ @param[in] ImageHandle ImageHandle of the loaded driver=0D
+ @param[in] SystemTable Pointer to the System Table=0D
+=0D
+ @retval EFI_SUCCESS The Protocol is installed.=0D
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial=
ize driver.=0D
+ @retval EFI_DEVICE_ERROR A device error occurred attempting to ini=
tialize the driver.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IntelVTdInitialize (=0D
+ IN EFI_HANDLE ImageHandle,=0D
+ IN EFI_SYSTEM_TABLE *SystemTable=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_HANDLE Handle;=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VTdLogInitialize ();=0D
+=0D
+ InitializeDmaProtection ();=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiIoMmuProtocolGuid, &mIntelVTd,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL, Status, 0);=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.inf
new file mode 100644
index 000000000..6f3c9e7df
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.inf
@@ -0,0 +1,92 @@
+## @file=0D
+# Intel VTd DXE Driver.=0D
+#=0D
+# This driver initializes VTd engine based upon DMAR ACPI tables=0D
+# and provide DMA protection to PCI or ACPI device.=0D
+#=0D
+# Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdCoreDxe=0D
+ MODULE_UNI_FILE =3D IntelVTdCoreDxe.uni=0D
+ FILE_GUID =3D 5c83381f-34d3-4672-b8f3-83c3d6f3b00e=
=0D
+ MODULE_TYPE =3D DXE_DRIVER=0D
+ VERSION_STRING =3D 1.0=0D
+ ENTRY_POINT =3D IntelVTdInitialize=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D IA32 X64 EBC=0D
+#=0D
+#=0D
+=0D
+[Sources]=0D
+ IntelVTdCoreDxe.c=0D
+ BmDma.c=0D
+ DmaProtection.c=0D
+ DmaProtection.h=0D
+ DmarAcpiTable.c=0D
+ PciInfo.c=0D
+ TranslationTable.c=0D
+ TranslationTableEx.c=0D
+ VtdReg.c=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ UefiDriverEntryPoint=0D
+ UefiBootServicesTableLib=0D
+ BaseLib=0D
+ IoLib=0D
+ HobLib=0D
+ PciSegmentLib=0D
+ BaseMemoryLib=0D
+ MemoryAllocationLib=0D
+ UefiLib=0D
+ CacheMaintenanceLib=0D
+ PerformanceLib=0D
+ PrintLib=0D
+ ReportStatusCodeLib=0D
+ IntelVTdPeiDxeLib=0D
+=0D
+[Guids]=0D
+ gVTdLogBufferHobGuid ## CONSUMES=0D
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi20TableGuid=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi10TableGuid=0D
+=0D
+[Protocols]=0D
+ gEdkiiIoMmuProtocolGuid ## PRODUCES=0D
+ gEfiPciIoProtocolGuid ## CONSUMES=0D
+ gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES=0D
+ gEdkiiPlatformVTdPolicyProtocolGuid ## SOMETIMES_CONSUMES=0D
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES=0D
+ gEdkiiVTdLogProtocolGuid ## PRODUCES=0D
+=0D
+[Pcd]=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdDxeLogBufferSize ## CONSUME=
S=0D
+=0D
+[Depex]=0D
+ gEfiPciRootBridgeIoProtocolGuid=0D
+=0D
+[UserExtensions.TianoCore."ExtraFiles"]=0D
+ IntelVTdCoreDxeExtra.uni=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.uni
new file mode 100644
index 000000000..73d2c83c4
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Module Localized Abstract and Description Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Intel VTd CORE DX=
E Driver."=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "This driver initi=
alizes VTd engine based upon DMAR ACPI tables and provide DMA protection to=
PCI or ACPI device."=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxeExtra.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCo=
reDxe/IntelVTdCoreDxeExtra.uni
new file mode 100644
index 000000000..7f1aec65e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxeExtra.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Localized Strings and Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+#string STR_PROPERTIES_MODULE_NAME=0D
+#language en-US=0D
+"Intel VTd CORE DXE Driver"=0D
+=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciI=
nfo.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
new file mode 100644
index 000000000..394ef734c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
@@ -0,0 +1,419 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ return (UINTN)-1;=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if ((PciSourceId->Bits.Bus =3D=3D SourceId.Bits.Bus) &&=0D
+ (PciSourceId->Bits.Device =3D=3D SourceId.Bits.Device) &&=0D
+ (PciSourceId->Bits.Function =3D=3D SourceId.Bits.Function) ) {=0D
+ return Index;=0D
+ }=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ )=0D
+{=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ UINTN PciDataIndex;=0D
+ UINTN Index;=0D
+ //PCI_DEVICE_DATA *NewPciDeviceData;=0D
+ PCI_DEVICE_INFORMATION *NewPciDeviceInfo;=0D
+ EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId;=0D
+=0D
+ PciDeviceInfo =3D mVtdUnitInformation[VtdIndex].PciDeviceInfo;=0D
+=0D
+ if (PciDeviceInfo->IncludeAllFlag) {=0D
+ //=0D
+ // Do not register device in other VTD Unit=0D
+ //=0D
+ for (Index =3D 0; Index < VtdIndex; Index++) {=0D
+ PciDataIndex =3D GetPciDataIndex (Index, Segment, SourceId);=0D
+ if (PciDataIndex !=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%=
02x already registered by Other Vtd(%d)\n", Segment, SourceId.Bits.Bus, Sou=
rceId.Bits.Device, SourceId.Bits.Function, Index));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ //=0D
+ // Register new=0D
+ //=0D
+=0D
+ if (PciDeviceInfo->PciDeviceDataNumber >=3D PciDeviceInfo->PciDeviceDa=
taMaxNumber) {=0D
+ //=0D
+ // Reallocate=0D
+ //=0D
+ NewPciDeviceInfo =3D AllocateZeroPool (sizeof (PCI_DEVICE_INFORMATIO=
N) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber + MA=
X_VTD_PCI_DATA_NUMBER));=0D
+ if (NewPciDeviceInfo =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ CopyMem (NewPciDeviceInfo, PciDeviceInfo, sizeof (PCI_DEVICE_INFORMA=
TION) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber +=
MAX_VTD_PCI_DATA_NUMBER));=0D
+ FreePool (PciDeviceInfo);=0D
+=0D
+ NewPciDeviceInfo->PciDeviceDataMaxNumber +=3D MAX_VTD_PCI_DATA_NUMBE=
R;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ }=0D
+=0D
+ ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceD=
ataMaxNumber);=0D
+=0D
+ PciSourceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciSourceId;=0D
+ PciSourceId->Bits.Bus =3D SourceId.Bits.Bus;=0D
+ PciSourceId->Bits.Device =3D SourceId.Bits.Device;=0D
+ PciSourceId->Bits.Function =3D SourceId.Bits.Function;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x"=
, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)=
);=0D
+=0D
+ PciDeviceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciDeviceId;=0D
+ if ((DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) =
||=0D
+ (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=
=0D
+ PciDeviceId->VendorId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->DeviceId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_DEVICE_ID_OFFSET));=0D
+ PciDeviceId->RevisionId =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS=
(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, =
PCI_REVISION_ID_OFFSET));=0D
+=0D
+ DEBUG ((DEBUG_INFO, " (%04x:%04x:%02x", PciDeviceId->VendorId, PciDe=
viceId->DeviceId, PciDeviceId->RevisionId));=0D
+=0D
+ if (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT)=
{=0D
+ PciDeviceId->SubsystemVendorId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->SubsystemDeviceId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_ID_OFFSET));=0D
+ DEBUG ((DEBUG_INFO, ":%04x:%04x", PciDeviceId->SubsystemVendorId, =
PciDeviceId->SubsystemDeviceId));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, ")"));=0D
+ }=0D
+=0D
+ PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDeviceDataNumber].Devic=
eType =3D DeviceType;=0D
+=0D
+ if ((DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) &&=
=0D
+ (DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=0D
+ DEBUG ((DEBUG_INFO, " (*)"));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "\n"));=0D
+=0D
+ PciDeviceInfo->PciDeviceDataNumber++;=0D
+ } else {=0D
+ if (CheckExist) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02=
x already registered\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, =
SourceId.Bits.Function));=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to register PCI device.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN VtdIndex;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT8 DeviceType;=0D
+ EFI_STATUS Status;=0D
+=0D
+ VtdIndex =3D (UINTN)Context;=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Dev=
ice, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, De=
vice, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, Segment, SourceId, DeviceType, F=
ALSE);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ UINT8 HeaderType;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT16 VendorID;=0D
+ UINT16 DeviceID;=0D
+ EFI_STATUS Status;=0D
+=0D
+ // Scan the PCI bus for devices=0D
+ for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) {=0D
+ for (Function =3D 0; Function <=3D PCI_MAX_FUNC; Function++) {=0D
+ VendorID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_VENDOR_ID_OFFSET));=0D
+ DeviceID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_DEVICE_ID_OFFSET));=0D
+ if (VendorID =3D=3D 0xFFFF && DeviceID =3D=3D 0xFFFF) {=0D
+ if (Function =3D=3D 0) {=0D
+ //=0D
+ // If function 0 is not implemented, do not scan other functions=
.=0D
+ //=0D
+ break;=0D
+ }=0D
+ continue;=0D
+ }=0D
+=0D
+ Status =3D Callback (Context, Segment, Bus, Device, Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus,=
Device, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(=
Segment, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=
=0D
+ DEBUG ((DEBUG_INFO," ScanPciBus: PCI bridge S%04x B%02x D%02x F=
%02x (SecondBus:%02x)\n", Segment, Bus, Device, Function, SecondaryBusNumbe=
r));=0D
+ if (SecondaryBusNumber !=3D 0) {=0D
+ Status =3D ScanPciBus (Context, Segment, SecondaryBusNumber, C=
allback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (Function =3D=3D 0) {=0D
+ HeaderType =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, B=
us, Device, 0, PCI_HEADER_TYPE_OFFSET));=0D
+ if ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) =3D=3D 0x00) {=0D
+ //=0D
+ // It is not a multi-function device, do not scan other function=
s.=0D
+ //=0D
+ break;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ UINTN HandleCount;=0D
+ EFI_HANDLE *HandleBuffer;=0D
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;=0D
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ScanAllPciBus ()\n"));=0D
+=0D
+ Status =3D gBS->LocateHandleBuffer (=0D
+ ByProtocol,=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ NULL,=0D
+ &HandleCount,=0D
+ &HandleBuffer=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Find %d root bridges\n", HandleCount));=0D
+=0D
+ for (Index =3D 0; Index < HandleCount; Index++) {=0D
+ Status =3D gBS->HandleProtocol (=0D
+ HandleBuffer[Index],=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ (VOID **) &PciRootBridgeIo=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) =
&Descriptors);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ while (Descriptors->Desc !=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ if (Descriptors->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_BUS) {=0D
+ break;=0D
+ }=0D
+ Descriptors++;=0D
+ }=0D
+=0D
+ if (Descriptors->Desc =3D=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ continue;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Scan root bridges : %d, Segment : %d, Bus : 0x%02X=
\n", Index, PciRootBridgeIo->SegmentNumber, Descriptors->AddrRangeMin));=0D
+ Status =3D ScanPciBus(Context, (UINT16) PciRootBridgeIo->SegmentNumber=
, (UINT8) Descriptors->AddrRangeMin, Callback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ FreePool(HandleBuffer);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ThisContextEntry;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ThisExtContextEntry;=0D
+ UINTN PciDataIndex;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ continue;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ continue;=0D
+ }=0D
+=0D
+// DEBUG ((DEBUG_INFO,"FindVtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n=
", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bit=
s.Function));=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D 0) {=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[So=
urceId.Index.RootIndex];=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_=
ADDRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.L=
owerContextTablePointerHi) ;=0D
+ ThisExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.Contex=
tIndex];=0D
+ if (ThisExtContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D ThisExtContextEntry;=0D
+ *ContextEntry =3D NULL;=0D
+ } else {=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId=
.Index.RootIndex];=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS=
(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointer=
Hi) ;=0D
+ ThisContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex=
];=0D
+ if (ThisContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D NULL;=0D
+ *ContextEntry =3D ThisContextEntry;=0D
+ }=0D
+=0D
+ return VtdIndex;=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/=
TranslationTable.c
new file mode 100644
index 000000000..37ca6e405
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
Table.c
@@ -0,0 +1,1112 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ )=0D
+{=0D
+ VOID *Addr;=0D
+=0D
+ Addr =3D AllocatePages (Pages);=0D
+ if (Addr =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ ZeroMem (Addr, EFI_PAGES_TO_SIZE(Pages));=0D
+ return Addr;=0D
+}=0D
+=0D
+/**=0D
+ Set second level paging entry attribute based upon IoMmuAccess.=0D
+=0D
+ @param[in] PtEntry The paging entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+**/=0D
+VOID=0D
+SetSecondLevelPagingEntryAttribute (=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PtEntry,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ PtEntry->Bits.Read =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_READ) !=3D 0)=
;=0D
+ PtEntry->Bits.Write =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_WRITE) !=3D 0=
);=0D
+}=0D
+=0D
+/**=0D
+ Create context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create context entry.=
=0D
+**/=0D
+EFI_STATUS=0D
+CreateContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTR=
Y_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CON=
TEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].RootEntryTable =3D (VTD_ROOT_ENTRY *)Buffe=
r;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId.I=
ndex.RootIndex];=0D
+ if (RootEntry->Bits.Present =3D=3D 0) {=0D
+ RootEntry->Bits.ContextTablePointerLo =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 12);=0D
+ RootEntry->Bits.ContextTablePointerHi =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 32);=0D
+ RootEntry->Bits.Present =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(R=
ootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi=
) ;=0D
+ ContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex];=0D
+ ContextEntry->Bits.TranslationType =3D 0;=0D
+ ContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n", mVtdUnitInform=
ation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.=
Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Roo=
tEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry table.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] MemoryBase The base of the memory.=0D
+ @param[in] MemoryLimit The limit of the memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntryTable (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 MemoryBase,=0D
+ IN UINT64 MemoryLimit,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Lvl5Start;=0D
+ UINTN Lvl5End;=0D
+ UINTN Lvl4PagesStart;=0D
+ UINTN Lvl4PagesEnd;=0D
+ UINTN Lvl4Start;=0D
+ UINTN Lvl4End;=0D
+ UINTN Lvl3Start;=0D
+ UINTN Lvl3End;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 EndAddress;=0D
+=0D
+ if (MemoryLimit =3D=3D 0) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ Lvl4PagesStart =3D 0;=0D
+ Lvl4PagesEnd =3D 0;=0D
+ Lvl4PtEntry =3D NULL;=0D
+ Lvl5PtEntry =3D NULL;=0D
+=0D
+ BaseAddress =3D ALIGN_VALUE_LOW(MemoryBase, SIZE_2MB);=0D
+ EndAddress =3D ALIGN_VALUE_UP(MemoryLimit, SIZE_2MB);=0D
+ DEBUG ((DEBUG_INFO,"CreateSecondLevelPagingEntryTable: BaseAddress - 0x%=
016lx, EndAddress - 0x%016lx\n", BaseAddress, EndAddress));=0D
+=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ SecondLevelPagingEntry =3D AllocateZeroPages (1);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry, EFI_PAG=
ES_TO_SIZE(1));=0D
+ }=0D
+=0D
+ //=0D
+ // If no access is needed, just create not present entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ return SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D RShiftU64 (EndAddress - 1, 48) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start, =
Lvl5End));=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+=0D
+ Lvl4PagesStart =3D (Lvl5Start<<9) | Lvl4Start;=0D
+ Lvl4PagesEnd =3D (Lvl5End<<9) | Lvl4End;=0D
+ DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", L=
vl4PagesStart, Lvl4PagesEnd));=0D
+=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ } else {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D Lvl5Start;=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, =
Lvl4End));=0D
+=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ }=0D
+=0D
+ for (Index5 =3D Lvl5Start; Index5 <=3D Lvl5End; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ Lvl5PtEntry[Index5].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index5));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl5PtEntry[Index5].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+ Lvl4Start =3D Lvl4PagesStart & 0x1FF;=0D
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {=0D
+ Lvl4End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;=0D
+ Lvl4PagesStart =3D (Index5+1)<<9;=0D
+ } else {=0D
+ Lvl4End =3D Lvl4PagesEnd & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\n=
", Index5, Lvl4Start, Lvl4End));=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D Lvl4Start; Index4 <=3D Lvl4End; Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ Lvl4PtEntry[Index4].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index4));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl3Start =3D RShiftU64 (BaseAddress, 30) & 0x1FF;=0D
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=3D EndAddres=
s) {=0D
+ Lvl3End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;=0D
+ } else {=0D
+ Lvl3End =3D RShiftU64 (EndAddress - 1, 30) & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n=
", Index4, Lvl3Start, Lvl3End));=0D
+=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D Lvl3Start; Index3 <=3D Lvl3End; Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ Lvl3PtEntry[Index3].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages =
(1);=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%=
x)!!!!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint6=
4, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_=
IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ Lvl2PtEntry[Index2].Uint64 =3D BaseAddress;=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuA=
ccess);=0D
+ Lvl2PtEntry[Index2].Bits.PageSize =3D 1;=0D
+ BaseAddress +=3D SIZE_2MB;=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UIN=
TN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN=
)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start], (UINTN)&=
Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex, =
SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess, Is5LevelPaging=
);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ if (mAbove4GMemoryLimit !=3D 0) {=0D
+ ASSERT (mAbove4GMemoryLimit > BASE_4GB);=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex=
, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess, Is5Le=
velPaging);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ }=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG((DEBUG_INFO, "CreateContextEntry - %d\n", Index));=0D
+=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.SMTS) {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));=0D
+ ASSERT(FALSE);=0D
+ Status =3D EFI_UNSUPPORTED;=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ } else {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ //=0D
+ // To compatible with pervious VTd engine=0D
+ // It was ECS(Extended Context Support) bit.=0D
+ //=0D
+ Status =3D CreateExtContextEntry (Index);=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ }=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR second level paging entry.=0D
+=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+DumpSecondLevelPagingEntry (=0D
+ IN VOID *SecondLevelPagingEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Index1;=0D
+ UINTN Lvl5IndexEnd;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl1PtEntry;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x, Is5LevelPagin=
g - %d\n", SecondLevelPagingEntry, Is5LevelPaging));=0D
+=0D
+ Lvl5IndexEnd =3D Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY) : 1;=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+=0D
+ for (Index5 =3D 0; Index5 < Lvl5IndexEnd; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n", Index=
5, Lvl5PtEntry[Index5].Uint64));=0D
+ }=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_EN=
TRY); Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index=
4, Lvl4PtEntry[Index4].Uint64));=0D
+ }=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_=
ENTRY); Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", In=
dex3, Lvl3PtEntry[Index3].Uint64));=0D
+ }=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ if (Lvl2PtEntry[Index2].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",=
Index2, Lvl2PtEntry[Index2].Uint64));=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Bits.PageSize =3D=3D 0) {=0D
+ Lvl1PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64=
BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.A=
ddressHi);=0D
+ for (Index1 =3D 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_P=
AGING_ENTRY); Index1++) {=0D
+ if (Lvl1PtEntry[Index1].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016=
lx\n", Index1, Lvl1PtEntry[Index1].Uint64));=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+}=0D
+=0D
+/**=0D
+ Invalid page entry.=0D
+=0D
+ @param VtdIndex The VTd engine index.=0D
+**/=0D
+VOID=0D
+InvalidatePageEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateVtdIOTLBGlobal (VtdIndex);=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D FALSE;=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D FALSE;=0D
+}=0D
+=0D
+#define VTD_PG_R BIT0=0D
+#define VTD_PG_W BIT1=0D
+#define VTD_PG_X BIT2=0D
+#define VTD_PG_EMT (BIT3 | BIT4 | BIT5)=0D
+#define VTD_PG_TM (BIT62)=0D
+=0D
+#define VTD_PG_PS BIT7=0D
+=0D
+#define PAGE_PROGATE_BITS (VTD_PG_TM | VTD_PG_EMT | VTD_PG_W | VT=
D_PG_R)=0D
+=0D
+#define PAGING_4K_MASK 0xFFF=0D
+#define PAGING_2M_MASK 0x1FFFFF=0D
+#define PAGING_1G_MASK 0x3FFFFFFF=0D
+=0D
+#define PAGING_VTD_INDEX_MASK 0x1FF=0D
+=0D
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull=0D
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull=0D
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull=0D
+=0D
+typedef enum {=0D
+ PageNone,=0D
+ Page4K,=0D
+ Page2M,=0D
+ Page1G,=0D
+} PAGE_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ PAGE_ATTRIBUTE Attribute;=0D
+ UINT64 Length;=0D
+ UINT64 AddressMask;=0D
+} PAGE_ATTRIBUTE_TABLE;=0D
+=0D
+PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D {=0D
+ {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},=0D
+ {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},=0D
+ {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},=0D
+};=0D
+=0D
+/**=0D
+ Return length according to page attributes.=0D
+=0D
+ @param[in] PageAttributes The page attribute of the page entry.=0D
+=0D
+ @return The length of page entry.=0D
+**/=0D
+UINTN=0D
+PageAttributeToLength (=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ for (Index =3D 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttrib=
uteTable[0]); Index++) {=0D
+ if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) {=0D
+ return (UINTN)mPageAttributeTable[Index].Length;=0D
+ }=0D
+ }=0D
+ return 0;=0D
+}=0D
+=0D
+/**=0D
+ Return page table entry to match the address.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd e=
ngine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in V=
Td table for the device.=0D
+ @param[in] Address The address to be checked.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+ @param[out] PageAttributes The page attribute of the page ent=
ry.=0D
+=0D
+ @return The page entry.=0D
+**/=0D
+VOID *=0D
+GetSecondLevelPageTableEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN PHYSICAL_ADDRESS Address,=0D
+ IN BOOLEAN Is5LevelPaging,=0D
+ OUT PAGE_ATTRIBUTE *PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index1;=0D
+ UINTN Index2;=0D
+ UINTN Index3;=0D
+ UINTN Index4;=0D
+ UINTN Index5;=0D
+ UINT64 *L1PageTable;=0D
+ UINT64 *L2PageTable;=0D
+ UINT64 *L3PageTable;=0D
+ UINT64 *L4PageTable;=0D
+ UINT64 *L5PageTable;=0D
+=0D
+ Index5 =3D ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;=0D
+ Index4 =3D ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;=0D
+ Index3 =3D ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;=0D
+ Index2 =3D ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;=0D
+ Index1 =3D ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ L5PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ L5PageTable[Index5] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\n=
", Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5], SIZE_4KB=
);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *=
)&L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5], sizeof(=
L5PageTable[Index5]));=0D
+ }=0D
+ L4PageTable =3D (UINT64 *)(UINTN)(L5PageTable[Index5] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ } else {=0D
+ L4PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ L4PageTable[Index4] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n",=
Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L4PageTable[Index4], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L4PageTable[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L4PageTable[Index4], sizeof(L4=
PageTable[Index4]));=0D
+ }=0D
+=0D
+ L3PageTable =3D (UINT64 *)(UINTN)(L4PageTable[Index4] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ L3PageTable[Index3] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!=
!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L3PageTable[Index3], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L3PageTable[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L3PageTable[Index3], sizeof(L3=
PageTable[Index3]));=0D
+ }=0D
+ if ((L3PageTable[Index3] & VTD_PG_PS) !=3D 0) {=0D
+ // 1G=0D
+ *PageAttribute =3D Page1G;=0D
+ return &L3PageTable[Index3];=0D
+ }=0D
+=0D
+ L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L2PageTable[Index2] =3D=3D 0) {=0D
+ L2PageTable[Index2] =3D Address & PAGING_2M_ADDRESS_MASK_64;=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L2PageTable[Index2], 0);=0D
+ L2PageTable[Index2] |=3D VTD_PG_PS;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L2PageTable[Index2], sizeof(L2=
PageTable[Index2]));=0D
+ }=0D
+ if ((L2PageTable[Index2] & VTD_PG_PS) !=3D 0) {=0D
+ // 2M=0D
+ *PageAttribute =3D Page2M;=0D
+ return &L2PageTable[Index2];=0D
+ }=0D
+=0D
+ // 4k=0D
+ L1PageTable =3D (UINT64 *)(UINTN)(L2PageTable[Index2] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if ((L1PageTable[Index1] =3D=3D 0) && (Address !=3D 0)) {=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ *PageAttribute =3D Page4K;=0D
+ return &L1PageTable[Index1];=0D
+}=0D
+=0D
+/**=0D
+ Modify memory attributes of page entry.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[out] IsModified TRUE means page table modified. FALSE mean=
s page table not modified.=0D
+**/=0D
+VOID=0D
+ConvertSecondLevelPageEntryAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN UINT64 IoMmuAccess,=0D
+ OUT BOOLEAN *IsModified=0D
+ )=0D
+{=0D
+ UINT64 CurrentPageEntry;=0D
+ UINT64 NewPageEntry;=0D
+=0D
+ CurrentPageEntry =3D PageEntry->Uint64;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry));=0D
+ NewPageEntry =3D PageEntry->Uint64;=0D
+ if (CurrentPageEntry !=3D NewPageEntry) {=0D
+ *IsModified =3D TRUE;=0D
+ DEBUG ((DEBUG_VERBOSE, "ConvertSecondLevelPageEntryAttribute 0x%lx", C=
urrentPageEntry));=0D
+ DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));=0D
+ } else {=0D
+ *IsModified =3D FALSE;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ This function returns if there is need to split page entry.=0D
+=0D
+ @param[in] BaseAddress The base address to be checked.=0D
+ @param[in] Length The length to be checked.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+=0D
+ @retval SplitAttributes on if there is need to split page entry.=0D
+**/=0D
+PAGE_ATTRIBUTE=0D
+NeedSplitPage (=0D
+ IN PHYSICAL_ADDRESS BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINT64 PageEntryLength;=0D
+=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+=0D
+ if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D Pag=
eEntryLength)) {=0D
+ return PageNone;=0D
+ }=0D
+=0D
+ if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) {=0D
+ return Page4K;=0D
+ }=0D
+=0D
+ return Page2M;=0D
+}=0D
+=0D
+/**=0D
+ This function splits one page entry to small page entries.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry to be splitted.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+ @param[in] SplitAttribute How to split the page entry.=0D
+=0D
+ @retval RETURN_SUCCESS The page entry is splitted.=0D
+ @retval RETURN_UNSUPPORTED The page entry does not support to be =
splitted.=0D
+ @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.=0D
+**/=0D
+RETURN_STATUS=0D
+SplitSecondLevelPage (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN PAGE_ATTRIBUTE PageAttribute,=0D
+ IN PAGE_ATTRIBUTE SplitAttribute=0D
+ )=0D
+{=0D
+ UINT64 BaseAddress;=0D
+ UINT64 *NewPageEntry;=0D
+ UINTN Index;=0D
+=0D
+ ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G);=0D
+=0D
+ if (PageAttribute =3D=3D Page2M) {=0D
+ //=0D
+ // Split 2M to 4K=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page4K);=0D
+ if (SplitAttribute =3D=3D Page4K) {=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_2M_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | (PageEn=
try->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else if (PageAttribute =3D=3D Page1G) {=0D
+ //=0D
+ // Split 1G to 2M=0D
+ // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K =
to get more compact page table.=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K);=
=0D
+ if ((SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K)) {=
=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_1G_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | VTD_PG_=
PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory on second level page entry=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetSecondLevelPagingAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry;=0D
+ PAGE_ATTRIBUTE PageAttribute;=0D
+ UINTN PageEntryLength;=0D
+ PAGE_ATTRIBUTE SplitAttribute;=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN IsEntryModified;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetSecondLevelPagingAttribute (%d) (0x%016lx - 0x=
%016lx : %x) \n", VtdIndex, BaseAddress, Length, IoMmuAccess));=0D
+ DEBUG ((DEBUG_VERBOSE," SecondLevelPagingEntry Base - 0x%x\n", SecondLe=
velPagingEntry));=0D
+=0D
+ if (BaseAddress !=3D ALIGN_VALUE(BaseAddress, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ if (Length !=3D ALIGN_VALUE(Length, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ while (Length !=3D 0) {=0D
+ PageEntry =3D GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagin=
gEntry, BaseAddress, mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAtt=
ribute);=0D
+ if (PageEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+ SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageAttribute);=
=0D
+ if (SplitAttribute =3D=3D PageNone) {=0D
+ ConvertSecondLevelPageEntryAttribute (VtdIndex, PageEntry, IoMmuAcce=
ss, &IsEntryModified);=0D
+ if (IsEntryModified) {=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ }=0D
+ //=0D
+ // Convert success, move to next=0D
+ //=0D
+ BaseAddress +=3D PageEntryLength;=0D
+ Length -=3D PageEntryLength;=0D
+ } else {=0D
+ Status =3D SplitSecondLevelPage (VtdIndex, PageEntry, PageAttribute,=
SplitAttribute);=0D
+ if (RETURN_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ //=0D
+ // Just split current page=0D
+ // Convert success in next around=0D
+ //=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (SecondLevelPagingEntry !=3D NULL) {=0D
+ Status =3D SetSecondLevelPagingAttribute (VtdIndex, DomainIdentifier, =
SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);=0D
+ }=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ EFI_STATUS Status;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+ UINTN PciDataIndex;=0D
+ UINT16 DomainIdentifier;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetAccessAttribute (S%04x B%02x D%02x F%02x) (0x%=
016lx - 0x%08x, %x)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function, BaseAddress, (UINTN)Length, IoMmuAccess));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"SetAccessAttribute - Pci device (S%04x B%02x D%02=
x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceData[PciDataIndex]=
.AccessCount++;=0D
+ //=0D
+ // DomainId should not be 0.=0D
+ //=0D
+ DomainIdentifier =3D (UINT16)(PciDataIndex + 1);=0D
+=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ if (ExtContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT3=
2) Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT3=
2) RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtC=
ontextEntry));=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
VtdIndex].ExtRootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=
=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtCont=
extEntry->Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry->Bits.S=
econdLevelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ if (ContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) =
Pt;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) =
RShiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*Context=
Entry));=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Vtd=
Index].RootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(Context=
Entry->Bits.SecondLevelPageTranslationPointerLo, ContextEntry->Bits.SecondL=
evelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Do not update FixedSecondLevelPagingEntry=0D
+ //=0D
+ if (SecondLevelPagingEntry !=3D mVtdUnitInformation[VtdIndex].FixedSecon=
dLevelPagingEntry) {=0D
+ Status =3D SetPageAttribute (=0D
+ VtdIndex,=0D
+ DomainIdentifier,=0D
+ SecondLevelPagingEntry,=0D
+ BaseAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR,"SetPageAttribute - %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ InvalidatePageEntry (VtdIndex);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"AlwaysEnablePageAttribute (S%04x B%02x D%02x F%02x)\=
n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Functio=
n));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"AlwaysEnablePageAttribute - Pci device (S%04x B%0=
2x D%02x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.De=
vice, SourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D=3D 0) =
{=0D
+ DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex));=
=0D
+ mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D CreateSe=
condLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCES=
S_WRITE, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ }=0D
+=0D
+ SecondLevelPagingEntry =3D mVtdUnitInformation[VtdIndex].FixedSecondLeve=
lPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32)=
Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32)=
RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdU=
nitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtCon=
textEntry));=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) Pt=
;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) RS=
hiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdUnit=
Information[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEn=
try));=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTableEx.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDx=
e/TranslationTableEx.c
new file mode 100644
index 000000000..c07afaf2b
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
TableEx.c
@@ -0,0 +1,108 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_=
ENTRY_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD=
_CONTEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].ExtRootEntryTable =3D (VTD_EXT_ROOT_ENTRY =
*)Buffer;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[Sour=
ceId.Index.RootIndex];=0D
+ if (ExtRootEntry->Bits.LowerPresent =3D=3D 0) {=0D
+ ExtRootEntry->Bits.LowerContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12);=0D
+ ExtRootEntry->Bits.LowerContextTablePointerHi =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 32);=0D
+ ExtRootEntry->Bits.LowerPresent =3D 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12) + 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerHi =3D (UINT32) RShiftU6=
4 (RShiftU64 ((UINT64)(UINTN)Buffer, 12) + 1, 20);=0D
+ ExtRootEntry->Bits.UpperPresent =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_AD=
DRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.Low=
erContextTablePointerHi) ;=0D
+ ExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.ContextIndex]=
;=0D
+ ExtContextEntry->Bits.TranslationType =3D 0;=0D
+ ExtContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ExtContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n", mVtdUnitInfor=
mation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId=
.Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+=0D
+=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Ext=
RootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdR=
eg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
new file mode 100644
index 000000000..56d621ff6
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
@@ -0,0 +1,759 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#define VTD_CAP_REG_NFR_MAX (256)=0D
+=0D
+UINTN mVtdUnitNumber =3D 0;=0D
+VTD_UNIT_INFORMATION *mVtdUnitInformation =3D NULL;=0D
+VTD_REGESTER_INFO *mVtdRegsInfoBuffer =3D NULL;=0D
+=0D
+BOOLEAN mVtdEnabled;=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *)Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_IQA_REG IqaReg;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[VtdIndex];=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ if (VtdUnitInfo->VerReg.Bits.Major <=3D 5) {=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for eng=
ine [%d]\n", VtdIndex));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ECapReg.Bits.QI =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations i=
nterface for engine [%d]\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 1;=0D
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n=
", VtdIndex));=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ if ((Reg32 & B_GSTS_REG_QIES) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n"));=
=0D
+ Reg32 &=3D (~B_GSTS_REG_QIES);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) !=3D 0);=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the Invalidation Queue Tail Register to zero.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);=0D
+=0D
+ //=0D
+ // Setup the IQ address, size and descriptor width through the Invalidat=
ion Queue Address Register=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ VtdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <=
< (VTD_INVALIDATION_QUEUE_SIZE + 7)));=0D
+ VtdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VtdUni=
tInfo->QiDescBufferSize));=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"))=
;=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ERROR_OUT=
_OF_RESOURCES, VtdUnitBaseAddress);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VtdUnitInfo=
->QiDescBufferSize));=0D
+ //=0D
+ // 4KB Aligned address=0D
+ //=0D
+ IqaReg.Uint64 =3D (UINT64) (UINTN) VtdUnitInfo->QiDescBuffer;=0D
+ IqaReg.Bits.DW =3D VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH;=0D
+ IqaReg.Bits.QS =3D VTD_INVALIDATION_QUEUE_SIZE;=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ DEBUG ((DEBUG_INFO, "IQA_REG =3D 0x%lx, IQH_REG =3D 0x%lx\n", IqaReg.Uin=
t64, MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));=0D
+=0D
+ //=0D
+ // Enable the queued invalidation interface through the Global Command R=
egister.=0D
+ // When enabled, hardware sets the QIES field in the Global Status Regis=
ter.=0D
+ //=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 |=3D B_GMCD_REG_QIE;=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG =3D =
0x%x\n", Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ENABLE, VtdUn=
itBaseAddress);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+SubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN QI_256_DESC *Desc=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_REGESTER_QI_INFO RegisterQi;=0D
+=0D
+ Status =3D VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress,=
Desc, FALSE);=0D
+ if (Status =3D=3D EFI_DEVICE_ERROR) {=0D
+ RegisterQi.BaseAddress =3D VtdUnitBaseAddress;=0D
+ RegisterQi.FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG=
);;=0D
+ RegisterQi.IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_R=
EG);=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_QI, &Register=
Qi, sizeof (VTD_REGESTER_QI_INFO));=0D
+=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, RegisterQi.FstsReg & (B_=
FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE));=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ R_CCMD_REG);=0D
+ if ((Reg64 & B_CCMD_REG_ICC) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC i=
s set for VTD(%d)\n",VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));=0D
+ Reg64 |=3D (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD=
_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + R_CCMD_REG);=0D
+ } while ((Reg64 & B_CCMD_REG_ICC) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC=
_GRAN(1) | QI_CC_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=0D
+ if ((Reg64 & B_IOTLB_REG_IVT) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set =
for VTD(%d)\n", VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));=0D
+ Reg64 |=3D (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdU=
nitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=
=0D
+ } while ((Reg64 & B_IOTLB_REG_IVT) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtd=
UnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVt=
dUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TY=
PE;=0D
+ QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0=
);=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (!mVtdEnabled) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext) {=0D
+ InvalidateContextCache (VtdIndex);=0D
+ }=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN DomainNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ if (mVtdRegsInfoBuffer =3D=3D NULL) {=0D
+ mVtdRegsInfoBuffer =3D AllocateZeroPool (sizeof (VTD_REGESTER_INFO) + =
sizeof (VTD_UINT128) * VTD_CAP_REG_NFR_MAX);=0D
+ ASSERT (mVtdRegsInfoBuffer !=3D NULL);=0D
+ }=0D
+=0D
+ //=0D
+ // Dump VTd error before DXE phase=0D
+ //=0D
+ DumpVtdIfError ();=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));=0D
+ mVtdUnitInformation[Index].VerReg.Uint32 =3D MmioRead32 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_VER_REG);=0D
+ DumpVtdVerRegs (&mVtdUnitInformation[Index].VerReg);=0D
+ mVtdUnitInformation[Index].CapReg.Uint64 =3D MmioRead64 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_CAP_REG);=0D
+ DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);=0D
+ mVtdUnitInformation[Index].ECapReg.Uint64 =3D MmioRead64 (mVtdUnitInfo=
rmation[Index].VtdUnitBaseAddress + R_ECAP_REG);=0D
+ DumpVtdECapRegs (&mVtdUnitInformation[Index].ECapReg);=0D
+=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) =3D=3D 0) {=
=0D
+ DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !=
!!!\n", Index));=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) =3D=
=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on V=
TD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));=0D
+ return ;=0D
+ }=0D
+=0D
+ DomainNumber =3D (UINTN)1 << (UINT8)((UINTN)mVtdUnitInformation[Index]=
.CapReg.Bits.ND * 2 + 4);=0D
+ if (mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumber >=3D=
DomainNumber) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >=3D DomainNumber(=
0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumbe=
r, DomainNumber));=0D
+ return ;=0D
+ }=0D
+=0D
+ Status =3D PerpareCacheInvalidationInterface(Index);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT(FALSE);=0D
+ return;=0D
+ }=0D
+ }=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Disable PMR in all VTd engine.=0D
+**/=0D
+VOID=0D
+DisablePmr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DisablePmr\n"));=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ Status =3D VtdLibDisablePmr (mVtdUnitInformation[Index].VtdUnitBaseAdd=
ress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_PMR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, Status);=0D
+ }=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Update Root Table Address Register=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] EnableADM TRUE - Enable ADM in TTM bits=0D
+**/=0D
+VOID=0D
+UpdateRootTableAddressRegister (=0D
+ IN UINTN VtdIndex,=0D
+ IN BOOLEAN EnableADM=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D NULL) {=0D
+ DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Vt=
dIndex].ExtRootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTab=
le | (EnableADM ? V_RTADDR_REG_TTM_ADM : BIT11);=0D
+ } else {=0D
+ DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[VtdIn=
dex].RootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable =
| (EnableADM ? V_RTADDR_REG_TTM_ADM : 0);=0D
+ }=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR=
_REG, Reg64);=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ BOOLEAN TEWasEnabled;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitBaseAddress =3D mVtdUnitInformation[Index].VtdUnitBaseAddress;=
=0D
+ DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] BAR [0x%x]\n", =
Index, VtdUnitBaseAddress));=0D
+=0D
+ //=0D
+ // Check TE was enabled or not.=0D
+ //=0D
+ TEWasEnabled =3D ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GS=
TS_REG_TE) =3D=3D B_GSTS_REG_TE);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ //=0D
+ // For implementations reporting Enhanced SRTP Support (ESRTPS) fiel=
d as=0D
+ // Clear in the Capability register, software must not modify this f=
ield while=0D
+ // DMA remapping is active (TES=3D1 in Global Status register).=0D
+ //=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable ADM=0D
+ //=0D
+ UpdateRootTableAddressRegister (Index, TRUE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+=0D
+ DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_T=
E);=0D
+=0D
+ } else {=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ InvalidateContextCache (Index);=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ InvalidateIOTLB (Index);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_ENABLE_DMAR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, 0);=0D
+ }=0D
+=0D
+ //=0D
+ // Need disable PMR, since we already setup translation table.=0D
+ //=0D
+ DisablePmr ();=0D
+=0D
+ mVtdEnabled =3D TRUE;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN SubIndex;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+=0D
+ VtdLibDisableDmar (VtdUnitInfo->VtdUnitBaseAddress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_DMAR, VtdUnitInfo->VtdUnitBaseAddre=
ss, 0);=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation !=3D 0) {=0D
+ //=0D
+ // Disable queued invalidation interface.=0D
+ //=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitInfo->VtdUnitBaseAd=
dress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_DISABLE, =
VtdUnitInfo->VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Free descriptor queue memory=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer !=3D NULL) {=0D
+ FreePages(VtdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VtdUnitInf=
o->QiDescBufferSize));=0D
+ VtdUnitInfo->QiDescBuffer =3D NULL;=0D
+ VtdUnitInfo->QiDescBufferSize =3D 0;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ }=0D
+ }=0D
+=0D
+ mVtdEnabled =3D FALSE;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+ DEBUG((DEBUG_INFO, "engine [%d] access\n", Index));=0D
+ for (SubIndex =3D 0; SubIndex < VtdUnitInfo->PciDeviceInfo->PciDeviceD=
ataNumber; SubIndex++) {=0D
+ DEBUG ((DEBUG_INFO, " PCI S%04X B%02x D%02x F%02x - %d\n",=0D
+ VtdUnitInfo->Segment,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Bus,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Device,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Function,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].AccessCount=0D
+ ));=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, " VerReg - 0x%x\n", VerReg->Uint32));=0D
+ DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major));=0D
+ DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ )=0D
+{=0D
+ DEBUG((DEBUG_INFO, " CapReg - 0x%x\n", CapReg->Uint64));=0D
+ DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND));=0D
+ DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL));=0D
+ DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF));=0D
+ DEBUG((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR));=0D
+ DEBUG((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR));=0D
+ DEBUG((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM));=0D
+ DEBUG((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW));=0D
+ DEBUG((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW));=0D
+ DEBUG((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR));=0D
+ DEBUG((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO));=0D
+ DEBUG((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS));=0D
+ DEBUG((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI));=0D
+ DEBUG((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR));=0D
+ DEBUG((DEBUG_INFO, " MAMV - 0x%x\n", CapReg-&
for pre-boot DMA protection feature.
Change-Id: I306a10b33a1fc4f80fa63c1fc1fb559aa054aa8c
Signed-off-by: Sheng Wei <w.sheng@...>
Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Cc: Jenny Huang <jenny.huang@...>
Cc: Robert Kowalewski <robert.kowalewski@...>
---
.../Feature/VTd/IntelVTdCoreDxe/BmDma.c | 547 +++++
.../VTd/IntelVTdCoreDxe/DmaProtection.c | 703 +++++++
.../VTd/IntelVTdCoreDxe/DmaProtection.h | 658 ++++++
.../VTd/IntelVTdCoreDxe/DmarAcpiTable.c | 398 ++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.c | 782 +++++++
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.inf | 92 +
.../VTd/IntelVTdCoreDxe/IntelVTdCoreDxe.uni | 14 +
.../IntelVTdCoreDxe/IntelVTdCoreDxeExtra.uni | 14 +
.../Feature/VTd/IntelVTdCoreDxe/PciInfo.c | 419 ++++
.../VTd/IntelVTdCoreDxe/TranslationTable.c | 1112 ++++++++++
.../VTd/IntelVTdCoreDxe/TranslationTableEx.c | 108 +
.../Feature/VTd/IntelVTdCoreDxe/VtdReg.c | 759 +++++++
.../Feature/VTd/IntelVTdCorePei/DmarTable.c | 301 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.c | 1099 ++++++++++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.h | 272 +++
.../VTd/IntelVTdCorePei/IntelVTdCorePei.inf | 70 +
.../VTd/IntelVTdCorePei/IntelVTdCorePei.uni | 14 +
.../IntelVTdCorePei/IntelVTdCorePeiExtra.uni | 14 +
.../VTd/IntelVTdCorePei/IntelVTdDmar.c | 731 +++++++
.../VTd/IntelVTdCorePei/TranslationTable.c | 926 +++++++++
.../Include/Guid/VtdLogDataHob.h | 151 ++
.../Include/Library/IntelVTdPeiDxeLib.h | 329 +++
.../IntelSiliconPkg/Include/Protocol/VtdLog.h | 59 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 21 +
.../Intel/IntelSiliconPkg/IntelSiliconPkg.dsc | 1 +
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.c | 1810 +++++++++++++++++
.../IntelVTdPeiDxeLib/IntelVTdPeiDxeLib.inf | 30 +
.../IntelVTdPeiDxeLibExt.inf | 34 +
28 files changed, 11468 insertions(+)
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/BmDma.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmaProtection.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/DmarAcpiTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxe.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/IntelVTdCoreDxeExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/PciInfo.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/TranslationTableEx.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreD=
xe/VtdReg.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/DmarTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePei.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdCorePeiExtra.uni
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/IntelVTdDmar.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreP=
ei/TranslationTable.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Guid/VtdLogDataHo=
b.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Library/IntelVTdP=
eiDxeLib.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Protocol/VtdLog.h
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.c
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLib.inf
create mode 100644 Silicon/Intel/IntelSiliconPkg/Library/IntelVTdPeiDxeLib=
/IntelVTdPeiDxeLibExt.inf
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDm=
a.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
new file mode 100644
index 000000000..41917a004
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/BmDma.c
@@ -0,0 +1,547 @@
+/** @file=0D
+ BmDma related function=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+// TBD: May make it a policy=0D
+#define DMA_MEMORY_TOP MAX_UINTN=0D
+//#define DMA_MEMORY_TOP 0x0000000001FFFFFFULL=0D
+=0D
+#define MAP_HANDLE_INFO_SIGNATURE SIGNATURE_32 ('H', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EFI_HANDLE DeviceHandle;=0D
+ UINT64 IoMmuAccess;=0D
+} MAP_HANDLE_INFO;=0D
+#define MAP_HANDLE_INFO_FROM_LINK(a) CR (a, MAP_HANDLE_INFO, Link, MAP_HAN=
DLE_INFO_SIGNATURE)=0D
+=0D
+#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')=0D
+typedef struct {=0D
+ UINT32 Signature;=0D
+ LIST_ENTRY Link;=0D
+ EDKII_IOMMU_OPERATION Operation;=0D
+ UINTN NumberOfBytes;=0D
+ UINTN NumberOfPages;=0D
+ EFI_PHYSICAL_ADDRESS HostAddress;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ LIST_ENTRY HandleList;=0D
+} MAP_INFO;=0D
+#define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)=0D
+=0D
+LIST_ENTRY gMaps =3D INITIALIZE_LIST_HEAD_VARIABLE(=
gMaps);=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ //=0D
+ // Find MapInfo according to DeviceAddress=0D
+ //=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo->DeviceAddress =3D=3D DeviceAddress) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapInfo =3D=3D NULL) || (MapInfo->DeviceAddress !=3D DeviceAddress)=
) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: DeviceAddress(0x%lx) =
- not found\n", DeviceAddress));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // Find MapHandleInfo according to DeviceHandle=0D
+ //=0D
+ MapHandleInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&MapInfo->HandleList)=0D
+ ; !IsNull (&MapInfo->HandleList, Link)=0D
+ ; Link =3D GetNextNode (&MapInfo->HandleList, Link)=0D
+ ) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (Link);=0D
+ if (MapHandleInfo->DeviceHandle =3D=3D DeviceHandle) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ if ((MapHandleInfo !=3D NULL) && (MapHandleInfo->DeviceHandle =3D=3D Dev=
iceHandle)) {=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ //=0D
+ // No DeviceHandle=0D
+ // Initialize and insert the MAP_HANDLE_INFO structure=0D
+ //=0D
+ MapHandleInfo =3D AllocatePool (sizeof (MAP_HANDLE_INFO));=0D
+ if (MapHandleInfo =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: %r\n", EFI_OUT_OF_RES=
OURCES));=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ return ;=0D
+ }=0D
+=0D
+ MapHandleInfo->Signature =3D MAP_HANDLE_INFO_SIGNATURE;=0D
+ MapHandleInfo->DeviceHandle =3D DeviceHandle;=0D
+ MapHandleInfo->IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ InsertTailList (&MapInfo->HandleList, &MapHandleInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+ MAP_INFO *MapInfo;=0D
+ EFI_PHYSICAL_ADDRESS DmaMemoryTop;=0D
+ BOOLEAN NeedRemap;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ if (NumberOfBytes =3D=3D NULL || DeviceAddress =3D=3D NULL ||=0D
+ Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: =3D=3D> 0x%08x - 0x%08x (%x)\n", HostA=
ddress, *NumberOfBytes, Operation));=0D
+=0D
+ //=0D
+ // Make sure that Operation is valid=0D
+ //=0D
+ if ((UINT32) Operation >=3D EdkiiIoMmuOperationMaximum) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ NeedRemap =3D FALSE;=0D
+ PhysicalAddress =3D (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;=0D
+=0D
+ DmaMemoryTop =3D DMA_MEMORY_TOP;=0D
+=0D
+ //=0D
+ // Alignment check=0D
+ //=0D
+ if ((*NumberOfBytes !=3D ALIGN_VALUE(*NumberOfBytes, SIZE_4KB)) ||=0D
+ (PhysicalAddress !=3D ALIGN_VALUE(PhysicalAddress, SIZE_4KB))) {=0D
+ if ((Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer) ||=0D
+ (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) {=0D
+ //=0D
+ // The input buffer might be a subset from IoMmuAllocateBuffer.=0D
+ // Skip the check.=0D
+ //=0D
+ } else {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+ }=0D
+=0D
+ if ((PhysicalAddress + *NumberOfBytes) >=3D DMA_MEMORY_TOP) {=0D
+ NeedRemap =3D TRUE;=0D
+ }=0D
+=0D
+ if (((Operation !=3D EdkiiIoMmuOperationBusMasterRead64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterWrite64 &&=0D
+ Operation !=3D EdkiiIoMmuOperationBusMasterCommonBuffer64)) &&=0D
+ ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {=0D
+ //=0D
+ // If the root bridge or the device cannot handle performing DMA above=
=0D
+ // 4GB but any part of the DMA transfer being mapped is above 4GB, the=
n=0D
+ // map the DMA transfer to a buffer below 4GB.=0D
+ //=0D
+ NeedRemap =3D TRUE;=0D
+ DmaMemoryTop =3D MIN (DmaMemoryTop, SIZE_4GB - 1);=0D
+ }=0D
+=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64) {=0D
+ if (NeedRemap) {=0D
+ //=0D
+ // Common Buffer operations can not be remapped. If the common buff=
er=0D
+ // is above 4GB, then it is not possible to generate a mapping, so r=
eturn=0D
+ // an error.=0D
+ //=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is=
=0D
+ // called later.=0D
+ //=0D
+ MapInfo =3D AllocatePool (sizeof (MAP_INFO));=0D
+ if (MapInfo =3D=3D NULL) {=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", EFI_OUT_OF_RESOURCES));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the MAP_INFO structure=0D
+ //=0D
+ MapInfo->Signature =3D MAP_INFO_SIGNATURE;=0D
+ MapInfo->Operation =3D Operation;=0D
+ MapInfo->NumberOfBytes =3D *NumberOfBytes;=0D
+ MapInfo->NumberOfPages =3D EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes=
);=0D
+ MapInfo->HostAddress =3D PhysicalAddress;=0D
+ MapInfo->DeviceAddress =3D DmaMemoryTop;=0D
+ InitializeListHead(&MapInfo->HandleList);=0D
+=0D
+ //=0D
+ // Allocate a buffer below 4GB to map the transfer to.=0D
+ //=0D
+ if (NeedRemap) {=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ EfiBootServicesData,=0D
+ MapInfo->NumberOfPages,=0D
+ &MapInfo->DeviceAddress=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (MapInfo);=0D
+ *NumberOfBytes =3D 0;=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuMap: %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+=0D
+ //=0D
+ // If this is a read operation from the Bus Master's point of view,=0D
+ // then copy the contents of the real buffer into the mapped buffer=0D
+ // so the Bus Master can read the contents of the real buffer.=0D
+ //=0D
+ if (Operation =3D=3D EdkiiIoMmuOperationBusMasterRead ||=0D
+ Operation =3D=3D EdkiiIoMmuOperationBusMasterRead64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+ } else {=0D
+ MapInfo->DeviceAddress =3D MapInfo->HostAddress;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ InsertTailList (&gMaps, &MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // The DeviceAddress is the address of the maped buffer below 4GB=0D
+ //=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ //=0D
+ // Return a pointer to the MAP_INFO structure in Mapping=0D
+ //=0D
+ *Mapping =3D MapInfo;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuMap: 0x%08x - 0x%08x <=3D=3D\n", *DeviceAdd=
ress, *Mapping));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_MAP, (UINT64) (*DeviceAddress), (UINT64=
) Operation);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ MAP_HANDLE_INFO *MapHandleInfo;=0D
+ LIST_ENTRY *Link;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuUnmap: 0x%08x\n", Mapping));=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuUnmap: %r\n", EFI_INVALID_PARAMETER));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+ RemoveEntryList (&MapInfo->Link);=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ //=0D
+ // remove all nodes in MapInfo->HandleList=0D
+ //=0D
+ while (!IsListEmpty (&MapInfo->HandleList)) {=0D
+ MapHandleInfo =3D MAP_HANDLE_INFO_FROM_LINK (MapInfo->HandleList.Forwa=
rdLink);=0D
+ RemoveEntryList (&MapHandleInfo->Link);=0D
+ FreePool (MapHandleInfo);=0D
+ }=0D
+=0D
+ if (MapInfo->DeviceAddress !=3D MapInfo->HostAddress) {=0D
+ //=0D
+ // If this is a write operation from the Bus Master's point of view,=0D
+ // then copy the contents of the mapped buffer into the real buffer=0D
+ // so the processor can read the contents of the real buffer.=0D
+ //=0D
+ if (MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite ||=0D
+ MapInfo->Operation =3D=3D EdkiiIoMmuOperationBusMasterWrite64) {=0D
+ CopyMem (=0D
+ (VOID *) (UINTN) MapInfo->HostAddress,=0D
+ (VOID *) (UINTN) MapInfo->DeviceAddress,=0D
+ MapInfo->NumberOfBytes=0D
+ );=0D
+ }=0D
+=0D
+ //=0D
+ // Free the mapped buffer and the MAP_INFO structure.=0D
+ //=0D
+ gBS->FreePages (MapInfo->DeviceAddress, MapInfo->NumberOfPages);=0D
+ }=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_UNMAP, MapInfo->NumberOfBytes, MapInfo-=
DeviceAddress);=0D+=0D
+ FreePool (Mapping);=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: =3D=3D> 0x%08x\n", Pages));=
=0D
+=0D
+ //=0D
+ // Validate Attributes=0D
+ //=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) !=
=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_UNSUPPORTED));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ //=0D
+ // Check for invalid inputs=0D
+ //=0D
+ if (HostAddress =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ //=0D
+ // The only valid memory types are EfiBootServicesData and=0D
+ // EfiRuntimeServicesData=0D
+ //=0D
+ if (MemoryType !=3D EfiBootServicesData &&=0D
+ MemoryType !=3D EfiRuntimeServicesData) {=0D
+ DEBUG ((DEBUG_ERROR, "IoMmuAllocateBuffer: %r\n", EFI_INVALID_PARAMETE=
R));=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ PhysicalAddress =3D DMA_MEMORY_TOP;=0D
+ if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) =3D=3D 0) {=
=0D
+ //=0D
+ // Limit allocations to memory below 4GB=0D
+ //=0D
+ PhysicalAddress =3D MIN (PhysicalAddress, SIZE_4GB - 1);=0D
+ }=0D
+ Status =3D gBS->AllocatePages (=0D
+ AllocateMaxAddress,=0D
+ MemoryType,=0D
+ Pages,=0D
+ &PhysicalAddress=0D
+ );=0D
+ if (!EFI_ERROR (Status)) {=0D
+ *HostAddress =3D (VOID *) (UINTN) PhysicalAddress;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_ALLOC_BUFFER, (UINT64) Pages, (UINT64=
) (*HostAddress));=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuAllocateBuffer: 0x%08x <=3D=3D\n", *HostAdd=
ress));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuFreeBuffer: 0x%\n", Pages));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_IOMMU_FREE_BUFFER, Pages, (UINT64) HostAddres=
s);=0D
+=0D
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages=
);=0D
+}=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ )=0D
+{=0D
+ MAP_INFO *MapInfo;=0D
+ LIST_ENTRY *Link;=0D
+=0D
+ if (Mapping =3D=3D NULL) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ MapInfo =3D NULL;=0D
+ for (Link =3D GetFirstNode (&gMaps)=0D
+ ; !IsNull (&gMaps, Link)=0D
+ ; Link =3D GetNextNode (&gMaps, Link)=0D
+ ) {=0D
+ MapInfo =3D MAP_INFO_FROM_LINK (Link);=0D
+ if (MapInfo =3D=3D Mapping) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ //=0D
+ // Mapping is not a valid value returned by Map()=0D
+ //=0D
+ if (MapInfo !=3D Mapping) {=0D
+ return EFI_INVALID_PARAMETER;=0D
+ }=0D
+=0D
+ *DeviceAddress =3D MapInfo->DeviceAddress;=0D
+ *NumberOfPages =3D MapInfo->NumberOfPages;=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.c
new file mode 100644
index 000000000..f2debe5a5
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.c
@@ -0,0 +1,703 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+UINT64 mBelow4GMemoryLimit;=0D
+UINT64 mAbove4GMemoryLimit;=0D
+=0D
+EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+VTD_ACCESS_REQUEST *mAccessRequest =3D NULL;=0D
+UINTN mAccessRequestCount =3D 0;=0D
+UINTN mAccessRequestMaxCount =3D 0;=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_ACCESS_REQUEST *NewAccessRequest;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // Optimization for memory.=0D
+ //=0D
+ // If the last record is to IoMmuAccess=3D0,=0D
+ // Check previous records and remove the matched entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ if ((mAccessRequest[Index].Segment =3D=3D Segment) &&=0D
+ (mAccessRequest[Index].SourceId.Uint16 =3D=3D SourceId.Uint16) &=
&=0D
+ (mAccessRequest[Index].BaseAddress =3D=3D BaseAddress) &&=0D
+ (mAccessRequest[Index].Length =3D=3D Length) &&=0D
+ (mAccessRequest[Index].IoMmuAccess !=3D 0)) {=0D
+ //=0D
+ // Remove this record [Index].=0D
+ // No need to add the new record.=0D
+ //=0D
+ if (Index !=3D mAccessRequestCount - 1) {=0D
+ CopyMem (=0D
+ &mAccessRequest[Index],=0D
+ &mAccessRequest[Index + 1],=0D
+ sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index=
)=0D
+ );=0D
+ }=0D
+ ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCE=
SS_REQUEST));=0D
+ mAccessRequestCount--;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequestCount >=3D mAccessRequestMaxCount) {=0D
+ NewAccessRequest =3D AllocateZeroPool (sizeof(*NewAccessRequest) * (mA=
ccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));=0D
+ if (NewAccessRequest =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mAccessRequestMaxCount +=3D MAX_VTD_ACCESS_REQUEST;=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest)=
* mAccessRequestCount);=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NewAccessRequest;=0D
+ }=0D
+=0D
+ ASSERT (mAccessRequestCount < mAccessRequestMaxCount);=0D
+=0D
+ mAccessRequest[mAccessRequestCount].Segment =3D Segment;=0D
+ mAccessRequest[mAccessRequestCount].SourceId =3D SourceId;=0D
+ mAccessRequest[mAccessRequestCount].BaseAddress =3D BaseAddress;=0D
+ mAccessRequest[mAccessRequestCount].Length =3D Length;=0D
+ mAccessRequest[mAccessRequestCount].IoMmuAccess =3D IoMmuAccess;=0D
+=0D
+ mAccessRequestCount++;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process Access Requests from before DMAR table is installed.=0D
+=0D
+**/=0D
+VOID=0D
+ProcessRequestedAccessAttribute (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));=0D
+=0D
+ for (Index =3D 0; Index < mAccessRequestCount; Index++) {=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "PCI(S%x.B%x.D%x.F%x) ",=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId.Bits.Bus,=0D
+ mAccessRequest[Index].SourceId.Bits.Device,=0D
+ mAccessRequest[Index].SourceId.Bits.Function=0D
+ ));=0D
+ DEBUG ((=0D
+ DEBUG_INFO,=0D
+ "(0x%lx~0x%lx) - %lx\n",=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ ));=0D
+ Status =3D SetAccessAttribute (=0D
+ mAccessRequest[Index].Segment,=0D
+ mAccessRequest[Index].SourceId,=0D
+ mAccessRequest[Index].BaseAddress,=0D
+ mAccessRequest[Index].Length,=0D
+ mAccessRequest[Index].IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));=0D
+ }=0D
+ }=0D
+=0D
+ if (mAccessRequest !=3D NULL) {=0D
+ FreePool (mAccessRequest);=0D
+ }=0D
+ mAccessRequest =3D NULL;=0D
+ mAccessRequestCount =3D 0;=0D
+ mAccessRequestMaxCount =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));=0D
+}=0D
+=0D
+/**=0D
+ Return UEFI memory map information.=0D
+=0D
+ @param[out] Below4GMemoryLimit The below 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+ @param[out] Above4GMemoryLimit The above 4GiB memory limit address or 0=
if insufficient resources exist to=0D
+ determine the address.=0D
+=0D
+**/=0D
+VOID=0D
+ReturnUefiMemoryMap (=0D
+ OUT UINT64 *Below4GMemoryLimit,=0D
+ OUT UINT64 *Above4GMemoryLimit=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;=0D
+ EFI_MEMORY_DESCRIPTOR *EfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR *NextEfiEntry;=0D
+ EFI_MEMORY_DESCRIPTOR TempEfiEntry;=0D
+ UINTN EfiMemoryMapSize;=0D
+ UINTN EfiMapKey;=0D
+ UINTN EfiDescriptorSize;=0D
+ UINT32 EfiDescriptorVersion;=0D
+ UINT64 MemoryBlockLength;=0D
+=0D
+ *Below4GMemoryLimit =3D 0;=0D
+ *Above4GMemoryLimit =3D 0;=0D
+=0D
+ //=0D
+ // Get the EFI memory map.=0D
+ //=0D
+ EfiMemoryMapSize =3D 0;=0D
+ EfiMemoryMap =3D NULL;=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ ASSERT (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+=0D
+ do {=0D
+ //=0D
+ // Use size returned back plus 1 descriptor for the AllocatePool.=0D
+ // We don't just multiply by 2 since the "for" loop below terminates o=
n=0D
+ // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize=
=0D
+ // we process bogus entries and create bogus E820 entries.=0D
+ //=0D
+ EfiMemoryMap =3D (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapS=
ize);=0D
+ if (EfiMemoryMap =3D=3D NULL) {=0D
+ ASSERT (EfiMemoryMap !=3D NULL);=0D
+ return;=0D
+ }=0D
+=0D
+ Status =3D gBS->GetMemoryMap (=0D
+ &EfiMemoryMapSize,=0D
+ EfiMemoryMap,=0D
+ &EfiMapKey,=0D
+ &EfiDescriptorSize,=0D
+ &EfiDescriptorVersion=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ FreePool (EfiMemoryMap);=0D
+ }=0D
+ } while (Status =3D=3D EFI_BUFFER_TOO_SMALL);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Sort memory map from low to high=0D
+ //=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ while (NextEfiEntry < EfiMemoryMapEnd) {=0D
+ if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {=0D
+ CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));=
=0D
+ CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTO=
R));=0D
+ }=0D
+=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptor=
Size);=0D
+ }=0D
+=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ NextEfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize)=
;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "MemoryMap:\n"));=0D
+ EfiEntry =3D EfiMemoryMap;=0D
+ EfiMemoryMapEnd =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + =
EfiMemoryMapSize);=0D
+ while (EfiEntry < EfiMemoryMapEnd) {=0D
+ MemoryBlockLength =3D (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12=
));=0D
+ DEBUG ((DEBUG_INFO, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry->T=
ype, EfiEntry->PhysicalStart, EfiEntry->PhysicalStart + MemoryBlockLength))=
;=0D
+ switch (EfiEntry->Type) {=0D
+ case EfiLoaderCode:=0D
+ case EfiLoaderData:=0D
+ case EfiBootServicesCode:=0D
+ case EfiBootServicesData:=0D
+ case EfiConventionalMemory:=0D
+ case EfiRuntimeServicesCode:=0D
+ case EfiRuntimeServicesData:=0D
+ case EfiACPIReclaimMemory:=0D
+ case EfiACPIMemoryNVS:=0D
+ case EfiReservedMemoryType:=0D
+ if ((EfiEntry->PhysicalStart + MemoryBlockLength) <=3D BASE_1MB) {=0D
+ //=0D
+ // Skip the memory block is under 1MB=0D
+ //=0D
+ } else if (EfiEntry->PhysicalStart >=3D BASE_4GB) {=0D
+ if (*Above4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Above4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ } else {=0D
+ if (*Below4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLen=
gth) {=0D
+ *Below4GMemoryLimit =3D EfiEntry->PhysicalStart + MemoryBlockLen=
gth;=0D
+ }=0D
+ }=0D
+ break;=0D
+ }=0D
+ EfiEntry =3D NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);=0D
+ }=0D
+=0D
+ FreePool (EfiMemoryMap);=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Result:\n"));=0D
+ DEBUG ((DEBUG_INFO, "Below4GMemoryLimit: 0x%016lx\n", *Below4GMemoryLim=
it));=0D
+ DEBUG ((DEBUG_INFO, "Above4GMemoryLimit: 0x%016lx\n", *Above4GMemoryLim=
it));=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackAlwaysEnablePageAttribute (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ EFI_STATUS Status;=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (Segment, SourceId);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device in the DeviceScope.=
=0D
+=0D
+ @param[in] DeviceScope the input device scope data structure=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device scope.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeDeviceScope (=0D
+ IN EDKII_PLATFORM_VTD_DEVICE_SCOPE *DeviceScope=0D
+ )=0D
+{=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceS=
cope->DeviceScope, &Bus, &Device, &Function);=0D
+=0D
+ if (DeviceScope->DeviceScope.Type =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYP=
E_PCI_BRIDGE) {=0D
+ //=0D
+ // Need scan the bridge and add all devices.=0D
+ //=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Device=
Scope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIS=
TER_OFFSET));=0D
+ Status =3D ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusN=
umber, ScanBusCallbackAlwaysEnablePageAttribute);=0D
+ return Status;=0D
+ } else {=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, Sour=
ceId);=0D
+ return Status;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device matching DeviceId.=0D
+=0D
+ @param[in] PciDeviceId the input PCI device ID=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device matching DeviceId.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributePciDeviceId (=0D
+ IN EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ UINTN PciIndex;=0D
+ PCI_DEVICE_DATA *PciDeviceData;=0D
+ EFI_STATUS Status;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ for (PciIndex =3D 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDevic=
eInfo->PciDeviceDataNumber; PciIndex++) {=0D
+ PciDeviceData =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciD=
eviceData[PciIndex];=0D
+=0D
+ if (((PciDeviceId->VendorId =3D=3D 0xFFFF) || (PciDeviceId->VendorId=
=3D=3D PciDeviceData->PciDeviceId.VendorId)) &&=0D
+ ((PciDeviceId->DeviceId =3D=3D 0xFFFF) || (PciDeviceId->DeviceId=
=3D=3D PciDeviceData->PciDeviceId.DeviceId)) &&=0D
+ ((PciDeviceId->RevisionId =3D=3D 0xFF) || (PciDeviceId->Revision=
Id =3D=3D PciDeviceData->PciDeviceId.RevisionId)) &&=0D
+ ((PciDeviceId->SubsystemVendorId =3D=3D 0xFFFF) || (PciDeviceId-=
SubsystemVendorId =3D=3D PciDeviceData->PciDeviceId.SubsystemVendorId)) &&==0D
+ ((PciDeviceId->SubsystemDeviceId =3D=3D 0xFFFF) || (PciDeviceId-=
SubsystemDeviceId =3D=3D PciDeviceData->PciDeviceId.SubsystemDeviceId)) ) ={=0D
+ Status =3D AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex=
].Segment, PciDeviceData->PciSourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ continue;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] DeviceInfo the exception device information=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device in the device info.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttributeExceptionDeviceInfo (=0D
+ IN EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *DeviceInfo=0D
+ )=0D
+{=0D
+ switch (DeviceInfo->Type) {=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:=0D
+ return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1))=
;=0D
+ case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:=0D
+ return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1))=
;=0D
+ default:=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN DeviceInfoCount;=0D
+ VOID *DeviceInfo;=0D
+ EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;=0D
+ UINTN Index;=0D
+=0D
+ //=0D
+ // It is optional.=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEdkiiPlatformVTdPolicyProtocolGuid,=0D
+ NULL,=0D
+ (VOID **)&mPlatformVTdPolicy=0D
+ );=0D
+ if (!EFI_ERROR(Status)) {=0D
+ DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));=0D
+ Status =3D mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPol=
icy, &DeviceInfoCount, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ ThisDeviceInfo =3D DeviceInfo;=0D
+ for (Index =3D 0; Index < DeviceInfoCount; Index++) {=0D
+ if (ThisDeviceInfo->Type =3D=3D EDKII_PLATFORM_VTD_EXCEPTION_DEVIC=
E_INFO_TYPE_END) {=0D
+ break;=0D
+ }=0D
+ AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);=0D
+ ThisDeviceInfo =3D (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo=
->Length);=0D
+ }=0D
+ FreePool (DeviceInfo);=0D
+ }=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd engine.=0D
+**/=0D
+VOID=0D
+SetupVtd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VOID *PciEnumerationComplete;=0D
+ UINTN Index;=0D
+ UINT64 Below4GMemoryLimit;=0D
+ UINT64 Above4GMemoryLimit;=0D
+ VTD_ROOT_TABLE_INFO RootTableInfo;=0D
+=0D
+ //=0D
+ // PCI Enumeration must be done=0D
+ //=0D
+ Status =3D gBS->LocateProtocol (=0D
+ &gEfiPciEnumerationCompleteProtocolGuid,=0D
+ NULL,=0D
+ &PciEnumerationComplete=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ ReturnUefiMemoryMap (&Below4GMemoryLimit, &Above4GMemoryLimit);=0D
+ Below4GMemoryLimit =3D ALIGN_VALUE_UP(Below4GMemoryLimit, SIZE_256MB);=0D
+ DEBUG ((DEBUG_INFO, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GM=
emoryLimit));=0D
+=0D
+ mBelow4GMemoryLimit =3D Below4GMemoryLimit;=0D
+ mAbove4GMemoryLimit =3D Above4GMemoryLimit;=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_SETUP_VTD, Below4GMemoryLimit, Above4GMemoryL=
imit);=0D
+=0D
+ //=0D
+ // 1. setup=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "ParseDmarAcpiTable\n"));=0D
+ Status =3D ParseDmarAcpiTableDrhd ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));=0D
+ PrepareVtdConfig ();=0D
+=0D
+ //=0D
+ // 2. initialization=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));=0D
+ Status =3D SetupTranslationTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ InitializePlatformVTdPolicy ();=0D
+=0D
+ ParseDmarAcpiTableRmrr ();=0D
+=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) =3D=3D 0) {=0D
+ //=0D
+ // Support IOMMU access attribute request recording before DMAR table =
is installed.=0D
+ // Here is to process the requests.=0D
+ //=0D
+ ProcessRequestedAccessAttribute ();=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInf=
ormation[Index].Segment));=0D
+=0D
+ if (mVtdUnitInformation[Index].ExtRootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
Index].ExtRootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 1, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[Index].RootEntryTable !=3D NULL) {=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Ind=
ex].RootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);=0D
+=0D
+ RootTableInfo.BaseAddress =3D mVtdUnitInformation[Index].VtdUnitBase=
Address;=0D
+ RootTableInfo.TableAddress =3D (UINT64) (UINTN) mVtdUnitInformation[=
Index].RootEntryTable;=0D
+ RootTableInfo.Is5LevelPaging =3D mVtdUnitInformation[Index].Is5Level=
Paging;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_ROOT_TABLE, 0, &RootTableInfo, sizeof=
(VTD_ROOT_TABLE_INFO));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // 3. enable=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar\n"));=0D
+ Status =3D EnableDmar ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "DumpVtdRegs\n"));=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Notification function of ACPI Table change.=0D
+=0D
+ This is a notification function registered on ACPI Table change event.=0D
+=0D
+ @param Event Event whose notification function is being invoked.=
=0D
+ @param Context Pointer to the notification function's context.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+AcpiNotificationFunc (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+=0D
+ Status =3D GetDmarAcpiTable ();=0D
+ if (EFI_ERROR (Status)) {=0D
+ if (Status =3D=3D EFI_ALREADY_STARTED) {=0D
+ gBS->CloseEvent (Event);=0D
+ }=0D
+ return;=0D
+ }=0D
+ SetupVtd ();=0D
+ gBS->CloseEvent (Event);=0D
+}=0D
+=0D
+/**=0D
+ Exit boot service callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnExitBootServices (=0D
+ IN EFI_EVENT Event,=0D
+ IN VOID *Context=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnExitBootServices\n"));=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) {=0D
+ DumpVtdRegsAll ();=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidate all\n"));=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAdd=
ress);=0D
+=0D
+ InvalidateContextCache (VtdIndex);=0D
+=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Legacy boot callback function.=0D
+=0D
+ @param[in] Event The event handle.=0D
+ @param[in] Context The event content.=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+OnLegacyBoot (=0D
+ EFI_EVENT Event,=0D
+ VOID *Context=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, "Vtd OnLegacyBoot\n"));=0D
+ DumpVtdRegsAll ();=0D
+ DisableDmar ();=0D
+ DumpVtdRegsAll ();=0D
+}=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_EVENT ExitBootServicesEvent;=0D
+ EFI_EVENT LegacyBootEvent;=0D
+ EFI_EVENT EventAcpi10;=0D
+ EFI_EVENT EventAcpi20;=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi10TableGuid,=0D
+ &EventAcpi10=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ VTD_TPL_LEVEL,=0D
+ AcpiNotificationFunc,=0D
+ NULL,=0D
+ &gEfiAcpi20TableGuid,=0D
+ &EventAcpi20=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ //=0D
+ // Signal the events initially for the case=0D
+ // that DMAR table has been installed.=0D
+ //=0D
+ gBS->SignalEvent (EventAcpi20);=0D
+ gBS->SignalEvent (EventAcpi10);=0D
+=0D
+ Status =3D gBS->CreateEventEx (=0D
+ EVT_NOTIFY_SIGNAL,=0D
+ TPL_CALLBACK,=0D
+ OnExitBootServices,=0D
+ NULL,=0D
+ &gEfiEventExitBootServicesGuid,=0D
+ &ExitBootServicesEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D EfiCreateEventLegacyBootEx (=0D
+ TPL_CALLBACK,=0D
+ OnLegacyBoot,=0D
+ NULL,=0D
+ &LegacyBootEvent=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ return ;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaP=
rotection.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
Protection.h
new file mode 100644
index 000000000..5cd59d18e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmaProtecti=
on.h
@@ -0,0 +1,658 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#ifndef _DMAR_PROTECTION_H_=0D
+#define _DMAR_PROTECTION_H_=0D
+=0D
+#include <Uefi.h>=0D
+#include <PiDxe.h>=0D
+=0D
+#include <Library/BaseLib.h>=0D
+#include <Library/BaseMemoryLib.h>=0D
+#include <Library/MemoryAllocationLib.h>=0D
+#include <Library/UefiBootServicesTableLib.h>=0D
+#include <Library/IoLib.h>=0D
+#include <Library/PciSegmentLib.h>=0D
+#include <Library/DebugLib.h>=0D
+#include <Library/UefiLib.h>=0D
+#include <Library/CacheMaintenanceLib.h>=0D
+#include <Library/PerformanceLib.h>=0D
+#include <Library/PrintLib.h>=0D
+#include <Library/ReportStatusCodeLib.h>=0D
+#include <Library/HobLib.h>=0D
+=0D
+#include <Guid/EventGroup.h>=0D
+#include <Guid/Acpi.h>=0D
+=0D
+#include <Protocol/VtdLog.h>=0D
+#include <Protocol/DxeSmmReadyToLock.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+#include <Protocol/PciIo.h>=0D
+#include <Protocol/PciEnumerationComplete.h>=0D
+#include <Protocol/PlatformVtdPolicy.h>=0D
+#include <Protocol/IoMmu.h>=0D
+#include <Protocol/PciRootBridgeIo.h>=0D
+=0D
+#include <IndustryStandard/Pci.h>=0D
+#include <IndustryStandard/DmaRemappingReportingTable.h>=0D
+#include <IndustryStandard/Vtd.h>=0D
+=0D
+#include <Library/IntelVTdPeiDxeLib.h>=0D
+=0D
+#define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32=
))=0D
+=0D
+#define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (=
~((Alignment) - 1)))=0D
+#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))=
=0D
+=0D
+#define VTD_TPL_LEVEL TPL_NOTIFY=0D
+=0D
+//=0D
+// Use 256-bit descriptor=0D
+// Queue size is 128.=0D
+//=0D
+#define VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH 1=0D
+#define VTD_INVALIDATION_QUEUE_SIZE 0=0D
+=0D
+//=0D
+// This is the initial max PCI DATA number.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_PCI_DATA_NUMBER 0x100=0D
+=0D
+typedef struct {=0D
+ UINTN VtdUnitBaseAddress;=0D
+ UINT16 Segment;=0D
+ VTD_VER_REG VerReg;=0D
+ VTD_CAP_REG CapReg;=0D
+ VTD_ECAP_REG ECapReg;=0D
+ VTD_ROOT_ENTRY *RootEntryTable;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntryTable;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *FixedSecondLevelPagingEntry;=0D
+ BOOLEAN HasDirtyContext;=0D
+ BOOLEAN HasDirtyPages;=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ BOOLEAN Is5LevelPaging;=0D
+ UINT8 EnableQueuedInvalidation;=0D
+ VOID *QiDescBuffer;=0D
+ UINTN QiDescBufferSize;=0D
+} VTD_UNIT_INFORMATION;=0D
+=0D
+//=0D
+// This is the initial max ACCESS request.=0D
+// The number may be enlarged later.=0D
+//=0D
+#define MAX_VTD_ACCESS_REQUEST 0x100=0D
+=0D
+typedef struct {=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 Length;=0D
+ UINT64 IoMmuAccess;=0D
+} VTD_ACCESS_REQUEST;=0D
+=0D
+=0D
+/**=0D
+ The scan bus callback function.=0D
+=0D
+ It is called in PCI bus scan for each PCI device under the bus.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The specific PCI device is processed in th=
e callback.=0D
+**/=0D
+typedef=0D
+EFI_STATUS=0D
+(EFIAPI *SCAN_BUS_FUNC_CALLBACK_FUNC) (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+extern EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;=0D
+=0D
+extern UINTN mVtdUnitNumber;=0D
+extern VTD_UNIT_INFORMATION *mVtdUnitInformation;=0D
+=0D
+extern UINT64 mBelow4GMemoryLimit;=0D
+extern UINT64 mAbove4GMemoryLimit;=0D
+=0D
+extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegs (=0D
+ IN UINTN VtdUnitBaseAddress=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers for all VTd engine.=0D
+**/=0D
+VOID=0D
+DumpVtdRegsAll (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd extended capability registers.=0D
+=0D
+ @param[in] ECapReg The extended capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdECapRegs (=0D
+ IN VTD_ECAP_REG *ECapReg=0D
+ );=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ );=0D
+=0D
+/**=0D
+ The scan bus callback function to always enable page attribute.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ );=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ );=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Parse DMAR RMRR table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR RMRR table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Dump VTd registers if there is error.=0D
+**/=0D
+VOID=0D
+DumpVtdIfError (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Initialize platform VTd policy.=0D
+**/=0D
+VOID=0D
+InitializePlatformVTdPolicy (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ );=0D
+=0D
+/**=0D
+ Get device information from mapping.=0D
+=0D
+ @param[in] Mapping The mapping.=0D
+ @param[out] DeviceAddress The device address of the mapping.=0D
+ @param[out] NumberOfPages The number of pages of the mapping.=0D
+=0D
+ @retval EFI_SUCCESS The device information is returned.=0D
+ @retval EFI_INVALID_PARAMETER The mapping is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+GetDeviceInfoFromMapping (=0D
+ IN VOID *Mapping,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT UINTN *NumberOfPages=0D
+ );=0D
+=0D
+/**=0D
+ Initialize DMA protection.=0D
+**/=0D
+VOID=0D
+InitializeDmaProtection (=0D
+ VOID=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ );=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ );=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ );=0D
+=0D
+/**=0D
+ Append VTd Access Request to global.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned=
.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinati=
on of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not support=
ed by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory rang=
e specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available t=
o modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while a=
ttempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+RequestAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ );=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ );=0D
+=0D
+#endif=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dmar=
AcpiTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Dma=
rAcpiTable.c
new file mode 100644
index 000000000..21f559983
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/DmarAcpiTab=
le.c
@@ -0,0 +1,398 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#pragma pack(1)=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT32 Entry;=0D
+} RSDT_TABLE;=0D
+=0D
+typedef struct {=0D
+ EFI_ACPI_DESCRIPTION_HEADER Header;=0D
+ UINT64 Entry;=0D
+} XSDT_TABLE;=0D
+=0D
+#pragma pack()=0D
+=0D
+EFI_ACPI_DMAR_HEADER *mAcpiDmarTable =3D NULL;=0D
+=0D
+/**=0D
+ Dump DMAR ACPI table.=0D
+**/=0D
+VOID=0D
+VtdDumpDmarTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ VtdLibDumpAcpiDmar (NULL, NULL, (EFI_ACPI_DMAR_HEADER *) (UINTN) mAcpiDm=
arTable);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_DMAR_TABLE, mAcpiDmarTable->Header.Length=
, (VOID *)mAcpiDmarTable, mAcpiDmarTable->Header.Length); =0D
+}=0D
+=0D
+/**=0D
+ Get PCI device information from DMAR DevScopeEntry.=0D
+=0D
+ @param[in] Segment The segment number.=0D
+ @param[in] DmarDevScopeEntry DMAR DevScopeEntry=0D
+ @param[out] Bus The bus number.=0D
+ @param[out] Device The device number.=0D
+ @param[out] Function The function number.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device information is returned.=0D
+**/=0D
+EFI_STATUS=0D
+GetPciBusDeviceFunction (=0D
+ IN UINT16 Segment,=0D
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,=0D
+ OUT UINT8 *Bus,=0D
+ OUT UINT8 *Device,=0D
+ OUT UINT8 *Function=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;=0D
+ UINT8 MyBus;=0D
+ UINT8 MyDevice;=0D
+ UINT8 MyFunction;=0D
+=0D
+ DmarPciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)((UINTN)(DmarDevScopeEntry + 1=
));=0D
+ MyBus =3D DmarDevScopeEntry->StartBusNumber;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ while ((UINTN)DmarPciPath + sizeof(EFI_ACPI_DMAR_PCI_PATH) < (UINTN)Dm=
arDevScopeEntry + DmarDevScopeEntry->Length) {=0D
+ MyBus =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, MyBus, M=
yDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=0D
+ DmarPciPath ++;=0D
+ MyDevice =3D DmarPciPath->Device;=0D
+ MyFunction =3D DmarPciPath->Function;=0D
+ }=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ break;=0D
+ }=0D
+=0D
+ *Bus =3D MyBus;=0D
+ *Device =3D MyDevice;=0D
+ *Function =3D MyFunction;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR DRHD table.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] DmarDrhd The DRHD table.=0D
+=0D
+ @retval EFI_SUCCESS The DRHD table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessDrhd (=0D
+ IN UINTN VtdIndex,=0D
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D AllocateZeroPool (sizeof=
(PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVICE_DATA) * MAX_VTD_PCI_DATA_NUM=
BER);=0D
+ if (mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D=3D NULL) {=0D
+ ASSERT (FALSE);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Segment =3D DmarDrhd->SegmentNu=
mber;=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress =3D (UINTN)DmarDrhd->Re=
gisterBaseAddress;=0D
+ DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, Dma=
rDrhd->RegisterBaseAddress));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->Segment =3D =
DmarDrhd->SegmentNumber;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataMaxNumber =3D =
MAX_VTD_PCI_DATA_NUMBER;=0D
+=0D
+ if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) !=3D 0)=
{=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D TRUE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: with INCLUDE ALL\n"));=0D
+=0D
+ Status =3D ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Sc=
anBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ } else {=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->IncludeAllFlag =3D FALSE;=
=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: without INCLUDE ALL\n"));=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarDrhd + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Len=
gth) {=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO," ProcessDrhd: "));=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ DEBUG ((DEBUG_INFO,"PCI Endpoint"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:=0D
+ DEBUG ((DEBUG_INFO,"IOAPIC"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:=0D
+ DEBUG ((DEBUG_INFO,"MSI Capable HPET"));=0D
+ break;=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:=0D
+ DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));=0D
+ break;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumb=
er, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, DmarDrhd->SegmentNumber, Sourc=
eId, DmarDevScopeEntry->Type, TRUE);=0D
+ if (EFI_ERROR (Status)) {=0D
+ //=0D
+ // There might be duplication for special device other than standard=
PCI device.=0D
+ //=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ switch (DmarDevScopeEntry->Type) {=0D
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Dmar=
Drhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGIST=
ER_OFFSET));=0D
+ Status =3D ScanPciBus ((VOID *)VtdIndex, DmarDrhd->SegmentNumber, Se=
condaryBusNumber, ScanBusCallbackRegisterPciDevice);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Process DMAR RMRR table.=0D
+=0D
+ @param[in] DmarRmrr The RMRR table.=0D
+=0D
+ @retval EFI_SUCCESS The RMRR table is processed.=0D
+**/=0D
+EFI_STATUS=0D
+ProcessRmrr (=0D
+ IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;=0D
+ UINT8 Bus;=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ EFI_STATUS Status;=0D
+ VTD_SOURCE_ID SourceId;=0D
+=0D
+ DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr-=
ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddres=s));=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U=
INTN)(DmarRmrr + 1));=0D
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Len=
gth) {=0D
+ if (DmarDevScopeEntry->Type !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_=
ENDPOINT) {=0D
+ DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%=
x] \n", DmarDevScopeEntry->Type));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Status =3D GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevSc=
opeEntry, &Bus, &Device, &Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->Segment=
Number, Bus, Device, Function));=0D
+=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+ Status =3D SetAccessAttribute (=0D
+ DmarRmrr->SegmentNumber,=0D
+ SourceId,=0D
+ DmarRmrr->ReservedMemoryRegionBaseAddress,=0D
+ DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->=
ReservedMemoryRegionBaseAddress,=0D
+ EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(=
(UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Get VTd engine number.=0D
+**/=0D
+UINTN=0D
+GetVtdEngineNumber (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ UINTN VtdIndex;=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ VtdIndex++;=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return VtdIndex ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableDrhd (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+ UINTN VtdIndex;=0D
+=0D
+ mVtdUnitNumber =3D GetVtdEngineNumber ();=0D
+ DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));=0D
+ ASSERT (mVtdUnitNumber > 0);=0D
+ if (mVtdUnitNumber =3D=3D 0) {=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ mVtdUnitInformation =3D AllocateZeroPool (sizeof(*mVtdUnitInformation) *=
mVtdUnitNumber);=0D
+ ASSERT (mVtdUnitInformation !=3D NULL);=0D
+ if (mVtdUnitInformation =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ VtdIndex =3D 0;=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_DRHD:=0D
+ ASSERT (VtdIndex < mVtdUnitNumber);=0D
+ Status =3D ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarH=
eader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ VtdIndex++;=0D
+=0D
+ break;=0D
+=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ ASSERT (VtdIndex =3D=3D mVtdUnitNumber);=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ VtdLibDumpPciDeviceInfo (NULL, NULL, mVtdUnitInformation[VtdIndex].Pci=
DeviceInfo);=0D
+=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_PCI_DEVICE,=0D
+ mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress,=
=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo,=0D
+ sizeof (PCI_DEVICE_INFORMATION) + sizeof (PCI_DEVI=
CE_DATA) * mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceDataNumber=
);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Parse DMAR DRHD table.=0D
+=0D
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.=0D
+**/=0D
+EFI_STATUS=0D
+ParseDmarAcpiTableRmrr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable=
+ 1));=0D
+ while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade=
r.Length) {=0D
+ switch (DmarHeader->Type) {=0D
+ case EFI_ACPI_DMAR_TYPE_RMRR:=0D
+ Status =3D ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ break;=0D
+ default:=0D
+ break;=0D
+ }=0D
+ DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + =
DmarHeader->Length);=0D
+ }=0D
+ return EFI_SUCCESS ;=0D
+}=0D
+=0D
+/**=0D
+ Get the DMAR ACPI table.=0D
+=0D
+ @retval EFI_SUCCESS The DMAR ACPI table is got.=0D
+ @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previousl=
y.=0D
+ @retval EFI_NOT_FOUND The DMAR ACPI table is not found.=0D
+**/=0D
+EFI_STATUS=0D
+GetDmarAcpiTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ if (mAcpiDmarTable !=3D NULL) {=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+=0D
+ mAcpiDmarTable =3D (EFI_ACPI_DMAR_HEADER *) EfiLocateFirstAcpiTable (=0D
+ EFI_ACPI_4_0_DMA_REMAPPING_T=
ABLE_SIGNATURE=0D
+ );=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ return EFI_NOT_FOUND;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));=0D
+ VtdDumpDmarTable();=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/I=
ntelVTdCoreDxe.c
new file mode 100644
index 000000000..dc7a7146d
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.c
@@ -0,0 +1,782 @@
+/** @file=0D
+ Intel VTd driver.=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Provides the controller-specific addresses required to access system mem=
ory from a=0D
+ DMA bus master.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Operation Indicates if the bus master is going to re=
ad or write to system memory.=0D
+ @param HostAddress The system memory address to map to the PC=
I controller.=0D
+ @param NumberOfBytes On input the number of bytes to map. On ou=
tput the number of bytes=0D
+ that were mapped.=0D
+ @param DeviceAddress The resulting map address for the bus mast=
er PCI controller to use to=0D
+ access the hosts HostAddress.=0D
+ @param Mapping A resulting value to pass to Unmap().=0D
+=0D
+ @retval EFI_SUCCESS The range was mapped for the returned Numb=
erOfBytes.=0D
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a comm=
on buffer.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to =
a lack of resources.=0D
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requ=
ested address.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuMap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EDKII_IOMMU_OPERATION Operation,=0D
+ IN VOID *HostAddress,=0D
+ IN OUT UINTN *NumberOfBytes,=0D
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,=0D
+ OUT VOID **Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Completes the Map() operation and releases any corresponding resources.=
=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Mapping The mapping value returned from Map().=0D
+=0D
+ @retval EFI_SUCCESS The range was unmapped.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned b=
y Map().=0D
+ @retval EFI_DEVICE_ERROR The data was not committed to the target s=
ystem memory.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuUnmap (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN VOID *Mapping=0D
+ );=0D
+=0D
+/**=0D
+ Allocates pages that are suitable for an OperationBusMasterCommonBuffer =
or=0D
+ OperationBusMasterCommonBuffer64 mapping.=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Type This parameter is not used and must be ign=
ored.=0D
+ @param MemoryType The type of memory to allocate, EfiBootSer=
vicesData or=0D
+ EfiRuntimeServicesData.=0D
+ @param Pages The number of pages to allocate.=0D
+ @param HostAddress A pointer to store the base system memory =
address of the=0D
+ allocated range.=0D
+ @param Attributes The requested bit mask of attributes for t=
he allocated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were allocated.=
=0D
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal =
attribute bits are=0D
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DU=
AL_ADDRESS_CYCLE.=0D
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.=0D
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuAllocateBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_ALLOCATE_TYPE Type,=0D
+ IN EFI_MEMORY_TYPE MemoryType,=0D
+ IN UINTN Pages,=0D
+ IN OUT VOID **HostAddress,=0D
+ IN UINT64 Attributes=0D
+ );=0D
+=0D
+/**=0D
+ Frees memory that was allocated with AllocateBuffer().=0D
+=0D
+ @param This The protocol instance pointer.=0D
+ @param Pages The number of pages to free.=0D
+ @param HostAddress The base system memory address of the allo=
cated range.=0D
+=0D
+ @retval EFI_SUCCESS The requested memory pages were freed.=0D
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress =
and Pages=0D
+ was not allocated with AllocateBuffer().=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuFreeBuffer (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN UINTN Pages,=0D
+ IN VOID *HostAddress=0D
+ );=0D
+=0D
+/**=0D
+ This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,=0D
+ based upon the DeviceAddress.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+**/=0D
+VOID=0D
+SyncDeviceHandleToMapInfo (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ );=0D
+=0D
+/**=0D
+ Convert the DeviceHandle to SourceId and Segment.=0D
+=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[out] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[out] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The Segment and SourceId are returned.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+**/=0D
+EFI_STATUS=0D
+DeviceHandleToSourceId (=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ OUT UINT16 *Segment,=0D
+ OUT VTD_SOURCE_ID *SourceId=0D
+ )=0D
+{=0D
+ EFI_PCI_IO_PROTOCOL *PciIo;=0D
+ UINTN Seg;=0D
+ UINTN Bus;=0D
+ UINTN Dev;=0D
+ UINTN Func;=0D
+ EFI_STATUS Status;=0D
+ EDKII_PLATFORM_VTD_DEVICE_INFO DeviceInfo;=0D
+=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (mPlatformVTdPolicy !=3D NULL) {=0D
+ Status =3D mPlatformVTdPolicy->GetDeviceId (mPlatformVTdPolicy, Device=
Handle, &DeviceInfo);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ *Segment =3D DeviceInfo.Segment;=0D
+ *SourceId =3D DeviceInfo.SourceId;=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D gBS->HandleProtocol (DeviceHandle, &gEfiPciIoProtocolGuid, (V=
OID **)&PciIo);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ Status =3D PciIo->GetLocation (PciIo, &Seg, &Bus, &Dev, &Func);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ *Segment =3D (UINT16)Seg;=0D
+ SourceId->Bits.Bus =3D (UINT8)Bus;=0D
+ SourceId->Bits.Device =3D (UINT8)Dev;=0D
+ SourceId->Bits.Function =3D (UINT8)Func;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] DeviceAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER DeviceAddress is not IoMmu Page size alig=
ned.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+VTdSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN EFI_PHYSICAL_ADDRESS DeviceAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINT16 Segment;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ CHAR8 PerfToken[sizeof("VTD(S0000.B00.D00.F00)")];=
=0D
+ UINT32 Identifier;=0D
+ VTD_PROTOCOL_SET_ATTRIBUTE LogSetAttribute;=0D
+=0D
+ DumpVtdIfError ();=0D
+=0D
+ Status =3D DeviceHandleToSourceId (DeviceHandle, &Segment, &SourceId);=0D
+ if (EFI_ERROR(Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE, "IoMmuSetAttribute: "));=0D
+ DEBUG ((DEBUG_VERBOSE, "PCI(S%x.B%x.D%x.F%x) ", Segment, SourceId.Bits.B=
us, SourceId.Bits.Device, SourceId.Bits.Function));=0D
+ DEBUG ((DEBUG_VERBOSE, "(0x%lx~0x%lx) - %lx\n", DeviceAddress, Length, I=
oMmuAccess));=0D
+=0D
+ if (mAcpiDmarTable =3D=3D NULL) {=0D
+ //=0D
+ // Record the entry to driver global variable.=0D
+ // As such once VTd is activated, the setting can be adopted.=0D
+ //=0D
+ if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) !=3D 0) {=0D
+ //=0D
+ // Force no IOMMU access attribute request recording before DMAR tab=
le is installed.=0D
+ //=0D
+ ASSERT_EFI_ERROR (EFI_NOT_READY);=0D
+ return EFI_NOT_READY;=0D
+ }=0D
+ Status =3D RequestAccessAttribute (Segment, SourceId, DeviceAddress, L=
ength, IoMmuAccess);=0D
+ } else {=0D
+ PERF_CODE (=0D
+ AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", S=
egment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_START_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=
=0D
+ );=0D
+=0D
+ Status =3D SetAccessAttribute (Segment, SourceId, DeviceAddress, Lengt=
h, IoMmuAccess);=0D
+=0D
+ PERF_CODE (=0D
+ Identifier =3D (Segment << 16) | SourceId.Uint16;=0D
+ PERF_END_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);=0D
+ );=0D
+ }=0D
+=0D
+ if (!EFI_ERROR(Status)) {=0D
+ SyncDeviceHandleToMapInfo (=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ LogSetAttribute.SourceId.Uint16 =3D SourceId.Uint16;=0D
+ LogSetAttribute.DeviceAddress =3D DeviceAddress;=0D
+ LogSetAttribute.Length =3D Length;=0D
+ LogSetAttribute.IoMmuAccess =3D IoMmuAccess;=0D
+ LogSetAttribute.Status =3D Status;=0D
+ VTdLogAddDataEvent (VTDLOG_DXE_IOMMU_SET_ATTRIBUTE, 0, &LogSetAttribute,=
sizeof (VTD_PROTOCOL_SET_ATTRIBUTE));=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set IOMMU attribute for a system memory.=0D
+=0D
+ If the IOMMU protocol exists, the system memory cannot be used=0D
+ for DMA by default.=0D
+=0D
+ When a device requests a DMA access for a system memory,=0D
+ the device driver need use SetAttribute() to update the IOMMU=0D
+ attribute to request DMA access (read and/or write).=0D
+=0D
+ The DeviceHandle is used to identify which device submits the request.=0D
+ The IOMMU implementation need translate the device path to an IOMMU devi=
ce ID,=0D
+ and set IOMMU hardware register accordingly.=0D
+ 1) DeviceHandle can be a standard PCI device.=0D
+ The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.=0D
+ The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.=0D
+ The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ=
|EDKII_IOMMU_ACCESS_WRITE.=0D
+ After the memory is used, the memory need set 0 to keep it being prot=
ected.=0D
+ 2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).=0D
+ The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDK=
II_IOMMU_ACCESS_WRITE.=0D
+=0D
+ @param[in] This The protocol instance pointer.=0D
+ @param[in] DeviceHandle The device who initiates the DMA access re=
quest.=0D
+ @param[in] Mapping The mapping value returned from Map().=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by DeviceAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.=0D
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned =
by Map().=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by Mapping.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IoMmuSetAttribute (=0D
+ IN EDKII_IOMMU_PROTOCOL *This,=0D
+ IN EFI_HANDLE DeviceHandle,=0D
+ IN VOID *Mapping,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_PHYSICAL_ADDRESS DeviceAddress;=0D
+ UINTN NumberOfPages;=0D
+ EFI_TPL OriginalTpl;=0D
+=0D
+ OriginalTpl =3D gBS->RaiseTPL (VTD_TPL_LEVEL);=0D
+=0D
+ Status =3D GetDeviceInfoFromMapping (Mapping, &DeviceAddress, &NumberOfP=
ages);=0D
+ if (!EFI_ERROR(Status)) {=0D
+ Status =3D VTdSetAttribute (=0D
+ This,=0D
+ DeviceHandle,=0D
+ DeviceAddress,=0D
+ EFI_PAGES_TO_SIZE(NumberOfPages),=0D
+ IoMmuAccess=0D
+ );=0D
+ }=0D
+=0D
+ gBS->RestoreTPL (OriginalTpl);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+EDKII_IOMMU_PROTOCOL mIntelVTd =3D {=0D
+ EDKII_IOMMU_PROTOCOL_REVISION,=0D
+ IoMmuSetAttribute,=0D
+ IoMmuMap,=0D
+ IoMmuUnmap,=0D
+ IoMmuAllocateBuffer,=0D
+ IoMmuFreeBuffer,=0D
+};=0D
+=0D
+UINT8 *mVtdLogBuffer =3D NULL;=0D
+=0D
+UINT8 *mVtdLogDxeFreeBuffer =3D NULL;=0D
+UINT32 mVtdLogDxeBufferUsed =3D 0;=0D
+=0D
+UINT32 mVtdLogPeiPostMemBufferUsed =3D 0;=0D
+=0D
+UINT8 mVtdLogPeiError =3D 0;=0D
+UINT16 mVtdLogDxeError =3D 0;=0D
+=0D
+/**=0D
+ Allocate memory buffer for VTd log items.=0D
+=0D
+ @param[in] MemorySize Required memory buffer size.=0D
+=0D
+ @retval Buffer address=0D
+=0D
+**/=0D
+UINT8 *=0D
+EFIAPI=0D
+VTdLogAllocMemory (=0D
+ IN CONST UINT32 MemorySize=0D
+ )=0D
+{=0D
+ UINT8 *Buffer;=0D
+=0D
+ Buffer =3D NULL;=0D
+ if (mVtdLogDxeFreeBuffer !=3D NULL) {=0D
+ if ((mVtdLogDxeBufferUsed + MemorySize) <=3D PcdGet32 (PcdVTdDxeLogBuf=
ferSize)) {=0D
+ Buffer =3D mVtdLogDxeFreeBuffer;=0D
+=0D
+ mVtdLogDxeFreeBuffer +=3D MemorySize;=0D
+ mVtdLogDxeBufferUsed +=3D MemorySize;=0D
+ } else {=0D
+ mVtdLogDxeError |=3D VTD_LOG_ERROR_BUFFER_FULL;=0D
+ }=0D
+ }=0D
+ return Buffer;=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Data1,=0D
+ IN CONST UINT64 Data2=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM *Item;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ Item =3D (VTDLOG_EVENT_2PARAM *) VTdLogAllocMemory (sizeof (VTDLOG_EVENT=
_2PARAM));=0D
+ if (Item !=3D NULL) {=0D
+ Item->Data1 =3D Data1;=0D
+ Item->Data2 =3D Data2;=0D
+=0D
+ Item->Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Add a new VTd log event with data.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Param parameter=0D
+ @param[in] Data Data=0D
+ @param[in] DataSize Data size=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogAddDataEvent (=0D
+ IN CONST VTDLOG_EVENT_TYPE EventType,=0D
+ IN CONST UINT64 Param,=0D
+ IN CONST VOID *Data,=0D
+ IN CONST UINT32 DataSize=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_CONTEXT *Item;=0D
+ UINT32 EventSize;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ } else if ((PcdGet8 (PcdVTdLogLevel) =3D=3D 1) && (EventType >=3D VTDLOG=
_DXE_ADVANCED)) {=0D
+ return;=0D
+ }=0D
+=0D
+ EventSize =3D sizeof (VTDLOG_EVENT_CONTEXT) + DataSize - 1;=0D
+=0D
+ Item =3D (VTDLOG_EVENT_CONTEXT *) VTdLogAllocMemory (EventSize);=0D
+ if (Item !=3D NULL) {=0D
+ Item->Param =3D Param;=0D
+ CopyMem (Item->Data, Data, DataSize);=0D
+=0D
+ Item->Header.DataSize =3D EventSize;=0D
+ Item->Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item->Header.Timestamp =3D AsmReadTsc ();=0D
+ }=0D
+}=0D
+ =0D
+/**=0D
+ Get Event Items From Pei Pre-Mem Buffer=0D
+=0D
+ @param[in] Buffer Pre-Memory data buffer.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log event=
=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromPeiPreMemBuffer (=0D
+ IN VTDLOG_PEI_PRE_MEM_INFO *InfoBuffer,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINT64 EventCount;=0D
+ VTDLOG_EVENT_2PARAM Event;=0D
+=0D
+ if (InfoBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ EventCount =3D 0;=0D
+ for (Index =3D 0; Index < VTD_LOG_PEI_PRE_MEM_BAR_MAX; Index++) {=0D
+ if (InfoBuffer[Index].Mode =3D=3D VTD_LOG_PEI_PRE_MEM_NOT_USED) {=0D
+ continue;=0D
+ }=0D
+ if (CallbackHandle) {=0D
+ Event.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Event.Header.Timestamp =3D 0;=0D
+=0D
+ Event.Header.LogType =3D ((UINT64) 1) << VTDLOG_PEI_PRE_MEM_DMA_PROT=
ECT;=0D
+ Event.Data1 =3D InfoBuffer[Index].BarAddress;=0D
+ Event.Data2 =3D InfoBuffer[Index].Mode;=0D
+ Event.Data2 |=3D InfoBuffer[Index].Status<<8;=0D
+ CallbackHandle (Context, &Event.Header);=0D
+ }=0D
+ EventCount++;=0D
+ }=0D
+=0D
+ return EventCount;=0D
+}=0D
+=0D
+/**=0D
+ Get Event Items From Pei Post-Mem/Dxe Buffer=0D
+=0D
+ @param[in] Buffer Data buffer.=0D
+ @param[in] BufferUsed Data buffer used.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdGetEventItemsFromBuffer (=0D
+ IN UINT8 *Buffer,=0D
+ IN UINT32 BufferUsed,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 Count;=0D
+ VTDLOG_EVENT_HEADER *Header;=0D
+=0D
+ Count =3D 0;=0D
+ if (Buffer !=3D NULL) {=0D
+ while (BufferUsed > 0) {=0D
+ Header =3D (VTDLOG_EVENT_HEADER *) Buffer;=0D
+ if (BufferUsed >=3D Header->DataSize) {=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, Header);=0D
+ }=0D
+ Buffer +=3D Header->DataSize;=0D
+ BufferUsed -=3D Header->DataSize;=0D
+ Count++;=0D
+ } else {=0D
+ BufferUsed =3D 0;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return Count;=0D
+}=0D
+=0D
+/**=0D
+ Generate the VTd log state.=0D
+=0D
+ @param[in] EventType Event type=0D
+ @param[in] Data1 First parameter=0D
+ @param[in] Data2 Second parameter=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdGenerateStateEvent (=0D
+ IN VTDLOG_EVENT_TYPE EventType,=0D
+ IN UINT64 Data1,=0D
+ IN UINT64 Data2,=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ VTDLOG_EVENT_2PARAM Item;=0D
+=0D
+ Item.Data1 =3D Data1;=0D
+ Item.Data2 =3D Data2;=0D
+=0D
+ Item.Header.DataSize =3D sizeof (VTDLOG_EVENT_2PARAM);=0D
+ Item.Header.LogType =3D (UINT64) 1 << EventType;=0D
+ Item.Header.Timestamp =3D 0;=0D
+=0D
+ if (CallbackHandle) {=0D
+ CallbackHandle (Context, &Item.Header);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Get the VTd log events.=0D
+ @param[in] Context Event context=0D
+ @param[in out] CallbackHandle Callback function for each VTd log eve=
nt=0D
+=0D
+ @retval UINT32 Number of events=0D
+**/=0D
+UINT64=0D
+EFIAPI=0D
+VTdLogGetEvents (=0D
+ IN VOID *Context,=0D
+ IN OUT EDKII_VTD_LOG_HANDLE_EVENT CallbackHandle=0D
+ )=0D
+{=0D
+ UINT64 Count;=0D
+ UINT8 *Buffer;=0D
+=0D
+ if (mVtdLogBuffer =3D=3D NULL) {=0D
+ return 0;=0D
+ }=0D
+=0D
+ //=0D
+ // PEI pre-memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (=
PcdVTdPeiPostMemLogBufferSize)];=0D
+ Count =3D VTdGetEventItemsFromPeiPreMemBuffer ((VTDLOG_PEI_PRE_MEM_INFO =
*) Buffer, Context, CallbackHandle);=0D
+=0D
+ //=0D
+ // PEI post memory phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[PcdGet32 (PcdVTdDxeLogBufferSize)];=0D
+ Count +=3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogPeiPostMemBufferUs=
ed, Context, CallbackHandle);=0D
+ if (mVtdLogPeiError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_PEI_BASIC, mVtdLogPeiError, 0, Context, =
CallbackHandle);=0D
+ Count++;=0D
+ }=0D
+=0D
+ //=0D
+ // DXE phase=0D
+ //=0D
+ Buffer =3D &mVtdLogBuffer[0];=0D
+ Count +=3D VTdGetEventItemsFromBuffer (Buffer, mVtdLogDxeBufferUsed, Con=
text, CallbackHandle);=0D
+ if (mVtdLogDxeError !=3D 0) {=0D
+ VTdGenerateStateEvent (VTDLOG_DXE_BASIC, mVtdLogDxeError, 0, Context, =
CallbackHandle);=0D
+ Count++;=0D
+ }=0D
+=0D
+ return Count;=0D
+}=0D
+=0D
+EDKII_VTD_LOG_PROTOCOL mIntelVTdLog =3D {=0D
+ EDKII_VTD_LOG_PROTOCOL_REVISION,=0D
+ VTdLogGetEvents=0D
+};=0D
+=0D
+/**=0D
+ Initializes the VTd Log.=0D
+=0D
+**/=0D
+VOID=0D
+EFIAPI=0D
+VTdLogInitialize(=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINT32 TotalBufferSize;=0D
+ EFI_STATUS Status;=0D
+ VOID *HobPtr;=0D
+ VTDLOG_PEI_BUFFER_HOB *HobPeiBuffer;=0D
+ EFI_HANDLE Handle;=0D
+ UINT32 BufferOffset;=0D
+=0D
+ if (PcdGet8 (PcdVTdLogLevel) =3D=3D 0) {=0D
+ return;=0D
+ }=0D
+=0D
+ if (mVtdLogBuffer !=3D NULL) {=0D
+ return;=0D
+ }=0D
+=0D
+ TotalBufferSize =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTd=
PeiPostMemLogBufferSize) + sizeof (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_P=
RE_MEM_BAR_MAX;=0D
+=0D
+ Status =3D gBS->AllocatePool (EfiBootServicesData, TotalBufferSize, &mVt=
dLogBuffer);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return;=0D
+ }=0D
+=0D
+ //=0D
+ // DXE Buffer=0D
+ //=0D
+ if (PcdGet32 (PcdVTdDxeLogBufferSize) > 0) {=0D
+ mVtdLogDxeFreeBuffer =3D mVtdLogBuffer;=0D
+ mVtdLogDxeBufferUsed =3D 0;=0D
+ }=0D
+=0D
+ //=0D
+ // Get PEI pre-memory buffer offset=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize) + PcdGet32 (PcdVTdPei=
PostMemLogBufferSize);=0D
+=0D
+ HobPtr =3D GetFirstGuidHob (&gVTdLogBufferHobGuid);=0D
+ if (HobPtr !=3D NULL) {=0D
+ HobPeiBuffer =3D GET_GUID_HOB_DATA (HobPtr);=0D
+=0D
+ //=0D
+ // Copy PEI pre-memory phase VTd log.=0D
+ //=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], &HobPeiBuffer->PreMemInfo, size=
of (VTDLOG_PEI_PRE_MEM_INFO) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+=0D
+ //=0D
+ // Copy PEI post-memory pase VTd log.=0D
+ //=0D
+ BufferOffset =3D PcdGet32 (PcdVTdDxeLogBufferSize);=0D
+ if (PcdGet32 (PcdVTdPeiPostMemLogBufferSize) > 0) {=0D
+ if (HobPeiBuffer->PostMemBufferUsed > 0) {=0D
+ mVtdLogPeiPostMemBufferUsed =3D HobPeiBuffer->PostMemBufferUsed;=0D
+ CopyMem (&mVtdLogBuffer[BufferOffset], (UINT8 *) (UINTN) HobPeiBuf=
fer->PostMemBuffer, mVtdLogPeiPostMemBufferUsed);=0D
+ }=0D
+ }=0D
+=0D
+ mVtdLogPeiError =3D HobPeiBuffer->VtdLogPeiError;=0D
+ } else {=0D
+ //=0D
+ // Do not find PEI Vtd log, clear PEI pre-memory phase buffer.=0D
+ //=0D
+ ZeroMem (&mVtdLogBuffer[BufferOffset], sizeof (VTDLOG_PEI_PRE_MEM_INFO=
) * VTD_LOG_PEI_PRE_MEM_BAR_MAX);=0D
+ }=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiVTdLogProtocolGuid,=0D
+ &mIntelVTdLog,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+}=0D
+=0D
+/**=0D
+ Initialize the VTd driver.=0D
+=0D
+ @param[in] ImageHandle ImageHandle of the loaded driver=0D
+ @param[in] SystemTable Pointer to the System Table=0D
+=0D
+ @retval EFI_SUCCESS The Protocol is installed.=0D
+ @retval EFI_OUT_OF_RESOURCES Not enough resources available to initial=
ize driver.=0D
+ @retval EFI_DEVICE_ERROR A device error occurred attempting to ini=
tialize the driver.=0D
+=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+IntelVTdInitialize (=0D
+ IN EFI_HANDLE ImageHandle,=0D
+ IN EFI_SYSTEM_TABLE *SystemTable=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_HANDLE Handle;=0D
+=0D
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) =3D=3D 0) {=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VTdLogInitialize ();=0D
+=0D
+ InitializeDmaProtection ();=0D
+=0D
+ Handle =3D NULL;=0D
+ Status =3D gBS->InstallMultipleProtocolInterfaces (=0D
+ &Handle,=0D
+ &gEdkiiIoMmuProtocolGuid, &mIntelVTd,=0D
+ NULL=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_INSTALL_IOMMU_PROTOCOL, Status, 0);=0D
+=0D
+ return Status;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.inf
new file mode 100644
index 000000000..6f3c9e7df
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.inf
@@ -0,0 +1,92 @@
+## @file=0D
+# Intel VTd DXE Driver.=0D
+#=0D
+# This driver initializes VTd engine based upon DMAR ACPI tables=0D
+# and provide DMA protection to PCI or ACPI device.=0D
+#=0D
+# Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D IntelVTdCoreDxe=0D
+ MODULE_UNI_FILE =3D IntelVTdCoreDxe.uni=0D
+ FILE_GUID =3D 5c83381f-34d3-4672-b8f3-83c3d6f3b00e=
=0D
+ MODULE_TYPE =3D DXE_DRIVER=0D
+ VERSION_STRING =3D 1.0=0D
+ ENTRY_POINT =3D IntelVTdInitialize=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D IA32 X64 EBC=0D
+#=0D
+#=0D
+=0D
+[Sources]=0D
+ IntelVTdCoreDxe.c=0D
+ BmDma.c=0D
+ DmaProtection.c=0D
+ DmaProtection.h=0D
+ DmarAcpiTable.c=0D
+ PciInfo.c=0D
+ TranslationTable.c=0D
+ TranslationTableEx.c=0D
+ VtdReg.c=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ IntelSiliconPkg/IntelSiliconPkg.dec=0D
+=0D
+[LibraryClasses]=0D
+ DebugLib=0D
+ UefiDriverEntryPoint=0D
+ UefiBootServicesTableLib=0D
+ BaseLib=0D
+ IoLib=0D
+ HobLib=0D
+ PciSegmentLib=0D
+ BaseMemoryLib=0D
+ MemoryAllocationLib=0D
+ UefiLib=0D
+ CacheMaintenanceLib=0D
+ PerformanceLib=0D
+ PrintLib=0D
+ ReportStatusCodeLib=0D
+ IntelVTdPeiDxeLib=0D
+=0D
+[Guids]=0D
+ gVTdLogBufferHobGuid ## CONSUMES=0D
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi20TableGuid=0D
+ ## CONSUMES ## SystemTable=0D
+ ## CONSUMES ## Event=0D
+ gEfiAcpi10TableGuid=0D
+=0D
+[Protocols]=0D
+ gEdkiiIoMmuProtocolGuid ## PRODUCES=0D
+ gEfiPciIoProtocolGuid ## CONSUMES=0D
+ gEfiPciEnumerationCompleteProtocolGuid ## CONSUMES=0D
+ gEdkiiPlatformVTdPolicyProtocolGuid ## SOMETIMES_CONSUMES=0D
+ gEfiPciRootBridgeIoProtocolGuid ## CONSUMES=0D
+ gEdkiiVTdLogProtocolGuid ## PRODUCES=0D
+=0D
+[Pcd]=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode ## CONSUMES=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdLogLevel ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiPostMemLogBufferSize ## CONSUME=
S=0D
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdDxeLogBufferSize ## CONSUME=
S=0D
+=0D
+[Depex]=0D
+ gEfiPciRootBridgeIoProtocolGuid=0D
+=0D
+[UserExtensions.TianoCore."ExtraFiles"]=0D
+ IntelVTdCoreDxeExtra.uni=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxe.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe=
/IntelVTdCoreDxe.uni
new file mode 100644
index 000000000..73d2c83c4
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxe.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Module Localized Abstract and Description Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+=0D
+#string STR_MODULE_ABSTRACT #language en-US "Intel VTd CORE DX=
E Driver."=0D
+=0D
+#string STR_MODULE_DESCRIPTION #language en-US "This driver initi=
alizes VTd engine based upon DMAR ACPI tables and provide DMA protection to=
PCI or ACPI device."=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Inte=
lVTdCoreDxeExtra.uni b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCo=
reDxe/IntelVTdCoreDxeExtra.uni
new file mode 100644
index 000000000..7f1aec65e
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/IntelVTdCor=
eDxeExtra.uni
@@ -0,0 +1,14 @@
+// /** @file=0D
+// IntelVTdDxe Localized Strings and Content=0D
+//=0D
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>=0D
+//=0D
+// SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+//=0D
+// **/=0D
+=0D
+#string STR_PROPERTIES_MODULE_NAME=0D
+#language en-US=0D
+"Intel VTd CORE DXE Driver"=0D
+=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciI=
nfo.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
new file mode 100644
index 000000000..394ef734c
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/PciInfo.c
@@ -0,0 +1,419 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Return the index of PCI data.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @return The index of the PCI data.=0D
+ @retval (UINTN)-1 The PCI data is not found.=0D
+**/=0D
+UINTN=0D
+GetPciDataIndex (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ return (UINTN)-1;=0D
+ }=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if ((PciSourceId->Bits.Bus =3D=3D SourceId.Bits.Bus) &&=0D
+ (PciSourceId->Bits.Device =3D=3D SourceId.Bits.Device) &&=0D
+ (PciSourceId->Bits.Function =3D=3D SourceId.Bits.Function) ) {=0D
+ return Index;=0D
+ }=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
+/**=0D
+ Register PCI device to VTd engine.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[in] DeviceType The DMAR device scope type.=0D
+ @param[in] CheckExist TRUE: ERROR will be returned if the PC=
I device is already registered.=0D
+ FALSE: SUCCESS will be returned if the=
PCI device is registered.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+ @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI d=
evice.=0D
+ @retval EFI_ALREADY_STARTED The device is already registered.=0D
+**/=0D
+EFI_STATUS=0D
+RegisterPciDevice (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT8 DeviceType,=0D
+ IN BOOLEAN CheckExist=0D
+ )=0D
+{=0D
+ PCI_DEVICE_INFORMATION *PciDeviceInfo;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ UINTN PciDataIndex;=0D
+ UINTN Index;=0D
+ //PCI_DEVICE_DATA *NewPciDeviceData;=0D
+ PCI_DEVICE_INFORMATION *NewPciDeviceInfo;=0D
+ EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId;=0D
+=0D
+ PciDeviceInfo =3D mVtdUnitInformation[VtdIndex].PciDeviceInfo;=0D
+=0D
+ if (PciDeviceInfo->IncludeAllFlag) {=0D
+ //=0D
+ // Do not register device in other VTD Unit=0D
+ //=0D
+ for (Index =3D 0; Index < VtdIndex; Index++) {=0D
+ PciDataIndex =3D GetPciDataIndex (Index, Segment, SourceId);=0D
+ if (PciDataIndex !=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%=
02x already registered by Other Vtd(%d)\n", Segment, SourceId.Bits.Bus, Sou=
rceId.Bits.Device, SourceId.Bits.Function, Index));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ //=0D
+ // Register new=0D
+ //=0D
+=0D
+ if (PciDeviceInfo->PciDeviceDataNumber >=3D PciDeviceInfo->PciDeviceDa=
taMaxNumber) {=0D
+ //=0D
+ // Reallocate=0D
+ //=0D
+ NewPciDeviceInfo =3D AllocateZeroPool (sizeof (PCI_DEVICE_INFORMATIO=
N) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber + MA=
X_VTD_PCI_DATA_NUMBER));=0D
+ if (NewPciDeviceInfo =3D=3D NULL) {=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+=0D
+ CopyMem (NewPciDeviceInfo, PciDeviceInfo, sizeof (PCI_DEVICE_INFORMA=
TION) + sizeof (PCI_DEVICE_DATA) * (PciDeviceInfo->PciDeviceDataMaxNumber +=
MAX_VTD_PCI_DATA_NUMBER));=0D
+ FreePool (PciDeviceInfo);=0D
+=0D
+ NewPciDeviceInfo->PciDeviceDataMaxNumber +=3D MAX_VTD_PCI_DATA_NUMBE=
R;=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ PciDeviceInfo =3D NewPciDeviceInfo;=0D
+ }=0D
+=0D
+ ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceD=
ataMaxNumber);=0D
+=0D
+ PciSourceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciSourceId;=0D
+ PciSourceId->Bits.Bus =3D SourceId.Bits.Bus;=0D
+ PciSourceId->Bits.Device =3D SourceId.Bits.Device;=0D
+ PciSourceId->Bits.Function =3D SourceId.Bits.Function;=0D
+=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02x"=
, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function)=
);=0D
+=0D
+ PciDeviceId =3D &PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDevice=
DataNumber].PciDeviceId;=0D
+ if ((DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) =
||=0D
+ (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=
=0D
+ PciDeviceId->VendorId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->DeviceId =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRES=
S(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function,=
PCI_DEVICE_ID_OFFSET));=0D
+ PciDeviceId->RevisionId =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS=
(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function, =
PCI_REVISION_ID_OFFSET));=0D
+=0D
+ DEBUG ((DEBUG_INFO, " (%04x:%04x:%02x", PciDeviceId->VendorId, PciDe=
viceId->DeviceId, PciDeviceId->RevisionId));=0D
+=0D
+ if (DeviceType =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT)=
{=0D
+ PciDeviceId->SubsystemVendorId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_VENDOR_ID_OFFSET));=0D
+ PciDeviceId->SubsystemDeviceId =3D PciSegmentRead16 (PCI_SEGMENT_L=
IB_ADDRESS(Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.=
Function, PCI_SUBSYSTEM_ID_OFFSET));=0D
+ DEBUG ((DEBUG_INFO, ":%04x:%04x", PciDeviceId->SubsystemVendorId, =
PciDeviceId->SubsystemDeviceId));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, ")"));=0D
+ }=0D
+=0D
+ PciDeviceInfo->PciDeviceData[PciDeviceInfo->PciDeviceDataNumber].Devic=
eType =3D DeviceType;=0D
+=0D
+ if ((DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) &&=
=0D
+ (DeviceType !=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {=0D
+ DEBUG ((DEBUG_INFO, " (*)"));=0D
+ }=0D
+ DEBUG ((DEBUG_INFO, "\n"));=0D
+=0D
+ PciDeviceInfo->PciDeviceDataNumber++;=0D
+ } else {=0D
+ if (CheckExist) {=0D
+ DEBUG ((DEBUG_INFO, " RegisterPciDevice: PCI S%04x B%02x D%02x F%02=
x already registered\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, =
SourceId.Bits.Function));=0D
+ return EFI_ALREADY_STARTED;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ The scan bus callback function to register PCI device.=0D
+=0D
+ @param[in] Context The context of the callback.=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Device The device of the source.=0D
+ @param[in] Function The function of the source.=0D
+=0D
+ @retval EFI_SUCCESS The PCI device is registered.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+ScanBusCallbackRegisterPciDevice (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN UINT8 Device,=0D
+ IN UINT8 Function=0D
+ )=0D
+{=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN VtdIndex;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT8 DeviceType;=0D
+ EFI_STATUS Status;=0D
+=0D
+ VtdIndex =3D (UINTN)Context;=0D
+ SourceId.Bits.Bus =3D Bus;=0D
+ SourceId.Bits.Device =3D Device;=0D
+ SourceId.Bits.Function =3D Function;=0D
+=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT;=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, Dev=
ice, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus, De=
vice, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ DeviceType =3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE;=0D
+ }=0D
+ }=0D
+=0D
+ Status =3D RegisterPciDevice (VtdIndex, Segment, SourceId, DeviceType, F=
ALSE);=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under the=
bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Bus The bus of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN UINT8 Bus,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ UINT8 Device;=0D
+ UINT8 Function;=0D
+ UINT8 SecondaryBusNumber;=0D
+ UINT8 HeaderType;=0D
+ UINT8 BaseClass;=0D
+ UINT8 SubClass;=0D
+ UINT16 VendorID;=0D
+ UINT16 DeviceID;=0D
+ EFI_STATUS Status;=0D
+=0D
+ // Scan the PCI bus for devices=0D
+ for (Device =3D 0; Device <=3D PCI_MAX_DEVICE; Device++) {=0D
+ for (Function =3D 0; Function <=3D PCI_MAX_FUNC; Function++) {=0D
+ VendorID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_VENDOR_ID_OFFSET));=0D
+ DeviceID =3D PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_DEVICE_ID_OFFSET));=0D
+ if (VendorID =3D=3D 0xFFFF && DeviceID =3D=3D 0xFFFF) {=0D
+ if (Function =3D=3D 0) {=0D
+ //=0D
+ // If function 0 is not implemented, do not scan other functions=
.=0D
+ //=0D
+ break;=0D
+ }=0D
+ continue;=0D
+ }=0D
+=0D
+ Status =3D Callback (Context, Segment, Bus, Device, Function);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+=0D
+ BaseClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus,=
Device, Function, PCI_CLASSCODE_OFFSET + 2));=0D
+ if (BaseClass =3D=3D PCI_CLASS_BRIDGE) {=0D
+ SubClass =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, Bus=
, Device, Function, PCI_CLASSCODE_OFFSET + 1));=0D
+ if (SubClass =3D=3D PCI_CLASS_BRIDGE_P2P) {=0D
+ SecondaryBusNumber =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(=
Segment, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));=
=0D
+ DEBUG ((DEBUG_INFO," ScanPciBus: PCI bridge S%04x B%02x D%02x F=
%02x (SecondBus:%02x)\n", Segment, Bus, Device, Function, SecondaryBusNumbe=
r));=0D
+ if (SecondaryBusNumber !=3D 0) {=0D
+ Status =3D ScanPciBus (Context, Segment, SecondaryBusNumber, C=
allback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ if (Function =3D=3D 0) {=0D
+ HeaderType =3D PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, B=
us, Device, 0, PCI_HEADER_TYPE_OFFSET));=0D
+ if ((HeaderType & HEADER_TYPE_MULTI_FUNCTION) =3D=3D 0x00) {=0D
+ //=0D
+ // It is not a multi-function device, do not scan other function=
s.=0D
+ //=0D
+ break;=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Scan PCI bus and invoke callback function for each PCI devices under all=
root bus.=0D
+=0D
+ @param[in] Context The context of the callback function.=
=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] Callback The callback function in PCI scan.=0D
+=0D
+ @retval EFI_SUCCESS The PCI devices under the bus are scaned.=
=0D
+**/=0D
+EFI_STATUS=0D
+ScanAllPciBus (=0D
+ IN VOID *Context,=0D
+ IN UINT16 Segment,=0D
+ IN SCAN_BUS_FUNC_CALLBACK_FUNC Callback=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+ UINTN HandleCount;=0D
+ EFI_HANDLE *HandleBuffer;=0D
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;=0D
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;=0D
+=0D
+ DEBUG ((DEBUG_INFO, "ScanAllPciBus ()\n"));=0D
+=0D
+ Status =3D gBS->LocateHandleBuffer (=0D
+ ByProtocol,=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ NULL,=0D
+ &HandleCount,=0D
+ &HandleBuffer=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Find %d root bridges\n", HandleCount));=0D
+=0D
+ for (Index =3D 0; Index < HandleCount; Index++) {=0D
+ Status =3D gBS->HandleProtocol (=0D
+ HandleBuffer[Index],=0D
+ &gEfiPciRootBridgeIoProtocolGuid,=0D
+ (VOID **) &PciRootBridgeIo=0D
+ );=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ Status =3D PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) =
&Descriptors);=0D
+ ASSERT_EFI_ERROR (Status);=0D
+=0D
+ while (Descriptors->Desc !=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ if (Descriptors->ResType =3D=3D ACPI_ADDRESS_SPACE_TYPE_BUS) {=0D
+ break;=0D
+ }=0D
+ Descriptors++;=0D
+ }=0D
+=0D
+ if (Descriptors->Desc =3D=3D ACPI_END_TAG_DESCRIPTOR) {=0D
+ continue;=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Scan root bridges : %d, Segment : %d, Bus : 0x%02X=
\n", Index, PciRootBridgeIo->SegmentNumber, Descriptors->AddrRangeMin));=0D
+ Status =3D ScanPciBus(Context, (UINT16) PciRootBridgeIo->SegmentNumber=
, (UINT8) Descriptors->AddrRangeMin, Callback);=0D
+ if (EFI_ERROR (Status)) {=0D
+ break;=0D
+ }=0D
+ }=0D
+=0D
+ FreePool(HandleBuffer);=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Find the VTd index by the Segment and SourceId.=0D
+=0D
+ @param[in] Segment The segment of the source.=0D
+ @param[in] SourceId The SourceId of the source.=0D
+ @param[out] ExtContextEntry The ExtContextEntry of the source.=0D
+ @param[out] ContextEntry The ContextEntry of the source.=0D
+=0D
+ @return The index of the VTd engine.=0D
+ @retval (UINTN)-1 The VTd engine is not found.=0D
+**/=0D
+UINTN=0D
+FindVtdIndexByPciDevice (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ OUT VTD_EXT_CONTEXT_ENTRY **ExtContextEntry,=0D
+ OUT VTD_CONTEXT_ENTRY **ContextEntry=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ThisContextEntry;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ThisExtContextEntry;=0D
+ UINTN PciDataIndex;=0D
+=0D
+ for (VtdIndex =3D 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {=0D
+ if (Segment !=3D mVtdUnitInformation[VtdIndex].Segment) {=0D
+ continue;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ if (PciDataIndex =3D=3D (UINTN)-1) {=0D
+ continue;=0D
+ }=0D
+=0D
+// DEBUG ((DEBUG_INFO,"FindVtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n=
", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bit=
s.Function));=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D 0) {=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[So=
urceId.Index.RootIndex];=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_=
ADDRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.L=
owerContextTablePointerHi) ;=0D
+ ThisExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.Contex=
tIndex];=0D
+ if (ThisExtContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D ThisExtContextEntry;=0D
+ *ContextEntry =3D NULL;=0D
+ } else {=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId=
.Index.RootIndex];=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS=
(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointer=
Hi) ;=0D
+ ThisContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex=
];=0D
+ if (ThisContextEntry->Bits.AddressWidth =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ *ExtContextEntry =3D NULL;=0D
+ *ContextEntry =3D ThisContextEntry;=0D
+ }=0D
+=0D
+ return VtdIndex;=0D
+ }=0D
+=0D
+ return (UINTN)-1;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/=
TranslationTable.c
new file mode 100644
index 000000000..37ca6e405
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
Table.c
@@ -0,0 +1,1112 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ );=0D
+=0D
+/**=0D
+ Allocate zero pages.=0D
+=0D
+ @param[in] Pages the number of pages.=0D
+=0D
+ @return the page address.=0D
+ @retval NULL No resource to allocate pages.=0D
+**/=0D
+VOID *=0D
+EFIAPI=0D
+AllocateZeroPages (=0D
+ IN UINTN Pages=0D
+ )=0D
+{=0D
+ VOID *Addr;=0D
+=0D
+ Addr =3D AllocatePages (Pages);=0D
+ if (Addr =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ ZeroMem (Addr, EFI_PAGES_TO_SIZE(Pages));=0D
+ return Addr;=0D
+}=0D
+=0D
+/**=0D
+ Set second level paging entry attribute based upon IoMmuAccess.=0D
+=0D
+ @param[in] PtEntry The paging entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+**/=0D
+VOID=0D
+SetSecondLevelPagingEntryAttribute (=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PtEntry,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ PtEntry->Bits.Read =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_READ) !=3D 0)=
;=0D
+ PtEntry->Bits.Write =3D ((IoMmuAccess & EDKII_IOMMU_ACCESS_WRITE) !=3D 0=
);=0D
+}=0D
+=0D
+/**=0D
+ Create context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create context entry.=
=0D
+**/=0D
+EFI_STATUS=0D
+CreateContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_ROOT_ENTRY *RootEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntryTable;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTR=
Y_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CON=
TEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].RootEntryTable =3D (VTD_ROOT_ENTRY *)Buffe=
r;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ RootEntry =3D &mVtdUnitInformation[VtdIndex].RootEntryTable[SourceId.I=
ndex.RootIndex];=0D
+ if (RootEntry->Bits.Present =3D=3D 0) {=0D
+ RootEntry->Bits.ContextTablePointerLo =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 12);=0D
+ RootEntry->Bits.ContextTablePointerHi =3D (UINT32) RShiftU64 ((UINT=
64)(UINTN)Buffer, 32);=0D
+ RootEntry->Bits.Present =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ContextEntryTable =3D (VTD_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_ADDRESS(R=
ootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi=
) ;=0D
+ ContextEntry =3D &ContextEntryTable[SourceId.Index.ContextIndex];=0D
+ ContextEntry->Bits.TranslationType =3D 0;=0D
+ ContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"Source: S%04x B%02x D%02x F%02x\n", mVtdUnitInform=
ation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.=
Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Roo=
tEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry table.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] MemoryBase The base of the memory.=0D
+ @param[in] MemoryLimit The limit of the memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntryTable (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 MemoryBase,=0D
+ IN UINT64 MemoryLimit,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Lvl5Start;=0D
+ UINTN Lvl5End;=0D
+ UINTN Lvl4PagesStart;=0D
+ UINTN Lvl4PagesEnd;=0D
+ UINTN Lvl4Start;=0D
+ UINTN Lvl4End;=0D
+ UINTN Lvl3Start;=0D
+ UINTN Lvl3End;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ UINT64 BaseAddress;=0D
+ UINT64 EndAddress;=0D
+=0D
+ if (MemoryLimit =3D=3D 0) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ Lvl4PagesStart =3D 0;=0D
+ Lvl4PagesEnd =3D 0;=0D
+ Lvl4PtEntry =3D NULL;=0D
+ Lvl5PtEntry =3D NULL;=0D
+=0D
+ BaseAddress =3D ALIGN_VALUE_LOW(MemoryBase, SIZE_2MB);=0D
+ EndAddress =3D ALIGN_VALUE_UP(MemoryLimit, SIZE_2MB);=0D
+ DEBUG ((DEBUG_INFO,"CreateSecondLevelPagingEntryTable: BaseAddress - 0x%=
016lx, EndAddress - 0x%016lx\n", BaseAddress, EndAddress));=0D
+=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ SecondLevelPagingEntry =3D AllocateZeroPages (1);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc LVL4 or LVL5 PT. \n"));=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)SecondLevelPagingEntry, EFI_PAG=
ES_TO_SIZE(1));=0D
+ }=0D
+=0D
+ //=0D
+ // If no access is needed, just create not present entry.=0D
+ //=0D
+ if (IoMmuAccess =3D=3D 0) {=0D
+ return SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D RShiftU64 (EndAddress - 1, 48) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl5Start - 0x%x, Lvl5End - 0x%x\n", Lvl5Start, =
Lvl5End));=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+=0D
+ Lvl4PagesStart =3D (Lvl5Start<<9) | Lvl4Start;=0D
+ Lvl4PagesEnd =3D (Lvl5End<<9) | Lvl4End;=0D
+ DEBUG ((DEBUG_INFO," Lvl4PagesStart - 0x%x, Lvl4PagesEnd - 0x%x\n", L=
vl4PagesStart, Lvl4PagesEnd));=0D
+=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ } else {=0D
+ Lvl5Start =3D RShiftU64 (BaseAddress, 48) & 0x1FF;=0D
+ Lvl5End =3D Lvl5Start;=0D
+=0D
+ Lvl4Start =3D RShiftU64 (BaseAddress, 39) & 0x1FF;=0D
+ Lvl4End =3D RShiftU64 (EndAddress - 1, 39) & 0x1FF;=0D
+ DEBUG ((DEBUG_INFO," Lvl4Start - 0x%x, Lvl4End - 0x%x\n", Lvl4Start, =
Lvl4End));=0D
+=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntr=
y;=0D
+ }=0D
+=0D
+ for (Index5 =3D Lvl5Start; Index5 <=3D Lvl5End; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ Lvl5PtEntry[Index5].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index5));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl5PtEntry[Index5].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl5PtEntry[Index5], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+ Lvl4Start =3D Lvl4PagesStart & 0x1FF;=0D
+ if (((Index5+1)<<9) > Lvl4PagesEnd) {=0D
+ Lvl4End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;;=0D
+ Lvl4PagesStart =3D (Index5+1)<<9;=0D
+ } else {=0D
+ Lvl4End =3D Lvl4PagesEnd & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl5(0x%x): Lvl4Start - 0x%x, Lvl4End - 0x%x\n=
", Index5, Lvl4Start, Lvl4End));=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D Lvl4Start; Index4 <=3D Lvl4End; Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ Lvl4PtEntry[Index4].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages (1=
);=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!=
\n", Index4));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl4PtEntry[Index4].Uint64,=
SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl4PtEntry[Index4], EDKII_IO=
MMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl3Start =3D RShiftU64 (BaseAddress, 30) & 0x1FF;=0D
+ if (ALIGN_VALUE_LOW(BaseAddress + SIZE_1GB, SIZE_1GB) <=3D EndAddres=
s) {=0D
+ Lvl3End =3D SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_ENTRY) - 1;=0D
+ } else {=0D
+ Lvl3End =3D RShiftU64 (EndAddress - 1, 30) & 0x1FF;=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," Lvl4(0x%x): Lvl3Start - 0x%x, Lvl3End - 0x%x\n=
", Index4, Lvl3Start, Lvl3End));=0D
+=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D Lvl3Start; Index3 <=3D Lvl3End; Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ Lvl3PtEntry[Index3].Uint64 =3D (UINT64)(UINTN)AllocateZeroPages =
(1);=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%=
x)!!!!!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl3PtEntry[Index3].Uint6=
4, SIZE_4KB);=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl3PtEntry[Index3], EDKII_=
IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ Lvl2PtEntry[Index2].Uint64 =3D BaseAddress;=0D
+ SetSecondLevelPagingEntryAttribute (&Lvl2PtEntry[Index2], IoMmuA=
ccess);=0D
+ Lvl2PtEntry[Index2].Bits.PageSize =3D 1;=0D
+ BaseAddress +=3D SIZE_2MB;=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)Lvl2PtEntry, SIZE_4KB);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl3PtEntry[Lvl3Start], (UIN=
TN)&Lvl3PtEntry[Lvl3End + 1] - (UINTN)&Lvl3PtEntry[Lvl3Start]);=0D
+ if (BaseAddress >=3D MemoryLimit) {=0D
+ break;=0D
+ }=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl4PtEntry[Lvl4Start], (UINTN=
)&Lvl4PtEntry[Lvl4End + 1] - (UINTN)&Lvl4PtEntry[Lvl4Start]);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&Lvl5PtEntry[Lvl5Start], (UINTN)&=
Lvl5PtEntry[Lvl5End + 1] - (UINTN)&Lvl5PtEntry[Lvl5Start]);=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Create second level paging entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+=0D
+ @return The second level paging entry.=0D
+**/=0D
+VTD_SECOND_LEVEL_PAGING_ENTRY *=0D
+CreateSecondLevelPagingEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT64 IoMmuAccess,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex, =
SecondLevelPagingEntry, 0, mBelow4GMemoryLimit, IoMmuAccess, Is5LevelPaging=
);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+=0D
+ if (mAbove4GMemoryLimit !=3D 0) {=0D
+ ASSERT (mAbove4GMemoryLimit > BASE_4GB);=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntryTable (VtdIndex=
, SecondLevelPagingEntry, SIZE_4GB, mAbove4GMemoryLimit, IoMmuAccess, Is5Le=
velPaging);=0D
+ if (SecondLevelPagingEntry =3D=3D NULL) {=0D
+ return NULL;=0D
+ }=0D
+ }=0D
+=0D
+ return SecondLevelPagingEntry;=0D
+}=0D
+=0D
+/**=0D
+ Setup VTd translation table.=0D
+=0D
+ @retval EFI_SUCCESS Setup translation table successfully.=0D
+ @retval EFI_OUT_OF_RESOURCE Setup translation table fail.=0D
+**/=0D
+EFI_STATUS=0D
+SetupTranslationTable (=0D
+ VOID=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ UINTN Index;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG((DEBUG_INFO, "CreateContextEntry - %d\n", Index));=0D
+=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.SMTS) {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));=0D
+ ASSERT(FALSE);=0D
+ Status =3D EFI_UNSUPPORTED;=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ } else {=0D
+ if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {=0D
+ //=0D
+ // To compatible with pervious VTd engine=0D
+ // It was ECS(Extended Context Support) bit.=0D
+ //=0D
+ Status =3D CreateExtContextEntry (Index);=0D
+ } else {=0D
+ Status =3D CreateContextEntry (Index);=0D
+ }=0D
+ }=0D
+=0D
+ if (EFI_ERROR (Status)) {=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump DMAR second level paging entry.=0D
+=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+**/=0D
+VOID=0D
+DumpSecondLevelPagingEntry (=0D
+ IN VOID *SecondLevelPagingEntry,=0D
+ IN BOOLEAN Is5LevelPaging=0D
+ )=0D
+{=0D
+ UINTN Index5;=0D
+ UINTN Index4;=0D
+ UINTN Index3;=0D
+ UINTN Index2;=0D
+ UINTN Index1;=0D
+ UINTN Lvl5IndexEnd;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl5PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl4PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl3PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl2PtEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *Lvl1PtEntry;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"DMAR Second Level Page Table:\n"));=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry Base - 0x%x, Is5LevelPagin=
g - %d\n", SecondLevelPagingEntry, Is5LevelPaging));=0D
+=0D
+ Lvl5IndexEnd =3D Is5LevelPaging ? SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY) : 1;=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+ Lvl5PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)SecondLevelPagingEntry;=
=0D
+=0D
+ for (Index5 =3D 0; Index5 < Lvl5IndexEnd; Index5++) {=0D
+ if (Is5LevelPaging) {=0D
+ if (Lvl5PtEntry[Index5].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl5Pt Entry(0x%03x) - 0x%016lx\n", Index=
5, Lvl5PtEntry[Index5].Uint64));=0D
+ }=0D
+ if (Lvl5PtEntry[Index5].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl4PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl5PtEntry[Index5].Bits.AddressLo, Lvl5PtEntry[Index5].Bits.Address=
Hi);=0D
+ }=0D
+=0D
+ for (Index4 =3D 0; Index4 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_EN=
TRY); Index4++) {=0D
+ if (Lvl4PtEntry[Index4].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl4Pt Entry(0x%03x) - 0x%016lx\n", Index=
4, Lvl4PtEntry[Index4].Uint64));=0D
+ }=0D
+ if (Lvl4PtEntry[Index4].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ Lvl3PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS_A=
DDRESS(Lvl4PtEntry[Index4].Bits.AddressLo, Lvl4PtEntry[Index4].Bits.Address=
Hi);=0D
+ for (Index3 =3D 0; Index3 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGING_=
ENTRY); Index3++) {=0D
+ if (Lvl3PtEntry[Index3].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl3Pt Entry(0x%03x) - 0x%016lx\n", In=
dex3, Lvl3PtEntry[Index3].Uint64));=0D
+ }=0D
+ if (Lvl3PtEntry[Index3].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+=0D
+ Lvl2PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64BITS=
_ADDRESS(Lvl3PtEntry[Index3].Bits.AddressLo, Lvl3PtEntry[Index3].Bits.Addre=
ssHi);=0D
+ for (Index2 =3D 0; Index2 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_PAGIN=
G_ENTRY); Index2++) {=0D
+ if (Lvl2PtEntry[Index2].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl2Pt Entry(0x%03x) - 0x%016lx\n",=
Index2, Lvl2PtEntry[Index2].Uint64));=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Uint64 =3D=3D 0) {=0D
+ continue;=0D
+ }=0D
+ if (Lvl2PtEntry[Index2].Bits.PageSize =3D=3D 0) {=0D
+ Lvl1PtEntry =3D (VTD_SECOND_LEVEL_PAGING_ENTRY *)(UINTN)VTD_64=
BITS_ADDRESS(Lvl2PtEntry[Index2].Bits.AddressLo, Lvl2PtEntry[Index2].Bits.A=
ddressHi);=0D
+ for (Index1 =3D 0; Index1 < SIZE_4KB/sizeof(VTD_SECOND_LEVEL_P=
AGING_ENTRY); Index1++) {=0D
+ if (Lvl1PtEntry[Index1].Uint64 !=3D 0) {=0D
+ DEBUG ((DEBUG_VERBOSE," Lvl1Pt Entry(0x%03x) - 0x%016=
lx\n", Index1, Lvl1PtEntry[Index1].Uint64));=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_VERBOSE,"=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\=
n"));=0D
+}=0D
+=0D
+/**=0D
+ Invalid page entry.=0D
+=0D
+ @param VtdIndex The VTd engine index.=0D
+**/=0D
+VOID=0D
+InvalidatePageEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateVtdIOTLBGlobal (VtdIndex);=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D FALSE;=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D FALSE;=0D
+}=0D
+=0D
+#define VTD_PG_R BIT0=0D
+#define VTD_PG_W BIT1=0D
+#define VTD_PG_X BIT2=0D
+#define VTD_PG_EMT (BIT3 | BIT4 | BIT5)=0D
+#define VTD_PG_TM (BIT62)=0D
+=0D
+#define VTD_PG_PS BIT7=0D
+=0D
+#define PAGE_PROGATE_BITS (VTD_PG_TM | VTD_PG_EMT | VTD_PG_W | VT=
D_PG_R)=0D
+=0D
+#define PAGING_4K_MASK 0xFFF=0D
+#define PAGING_2M_MASK 0x1FFFFF=0D
+#define PAGING_1G_MASK 0x3FFFFFFF=0D
+=0D
+#define PAGING_VTD_INDEX_MASK 0x1FF=0D
+=0D
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull=0D
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull=0D
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull=0D
+=0D
+typedef enum {=0D
+ PageNone,=0D
+ Page4K,=0D
+ Page2M,=0D
+ Page1G,=0D
+} PAGE_ATTRIBUTE;=0D
+=0D
+typedef struct {=0D
+ PAGE_ATTRIBUTE Attribute;=0D
+ UINT64 Length;=0D
+ UINT64 AddressMask;=0D
+} PAGE_ATTRIBUTE_TABLE;=0D
+=0D
+PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] =3D {=0D
+ {Page4K, SIZE_4KB, PAGING_4K_ADDRESS_MASK_64},=0D
+ {Page2M, SIZE_2MB, PAGING_2M_ADDRESS_MASK_64},=0D
+ {Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},=0D
+};=0D
+=0D
+/**=0D
+ Return length according to page attributes.=0D
+=0D
+ @param[in] PageAttributes The page attribute of the page entry.=0D
+=0D
+ @return The length of page entry.=0D
+**/=0D
+UINTN=0D
+PageAttributeToLength (=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ for (Index =3D 0; Index < sizeof(mPageAttributeTable)/sizeof(mPageAttrib=
uteTable[0]); Index++) {=0D
+ if (PageAttribute =3D=3D mPageAttributeTable[Index].Attribute) {=0D
+ return (UINTN)mPageAttributeTable[Index].Length;=0D
+ }=0D
+ }=0D
+ return 0;=0D
+}=0D
+=0D
+/**=0D
+ Return page table entry to match the address.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd e=
ngine.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in V=
Td table for the device.=0D
+ @param[in] Address The address to be checked.=0D
+ @param[in] Is5LevelPaging If it is the 5 level paging.=0D
+ @param[out] PageAttributes The page attribute of the page ent=
ry.=0D
+=0D
+ @return The page entry.=0D
+**/=0D
+VOID *=0D
+GetSecondLevelPageTableEntry (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN PHYSICAL_ADDRESS Address,=0D
+ IN BOOLEAN Is5LevelPaging,=0D
+ OUT PAGE_ATTRIBUTE *PageAttribute=0D
+ )=0D
+{=0D
+ UINTN Index1;=0D
+ UINTN Index2;=0D
+ UINTN Index3;=0D
+ UINTN Index4;=0D
+ UINTN Index5;=0D
+ UINT64 *L1PageTable;=0D
+ UINT64 *L2PageTable;=0D
+ UINT64 *L3PageTable;=0D
+ UINT64 *L4PageTable;=0D
+ UINT64 *L5PageTable;=0D
+=0D
+ Index5 =3D ((UINTN)RShiftU64 (Address, 48)) & PAGING_VTD_INDEX_MASK;=0D
+ Index4 =3D ((UINTN)RShiftU64 (Address, 39)) & PAGING_VTD_INDEX_MASK;=0D
+ Index3 =3D ((UINTN)Address >> 30) & PAGING_VTD_INDEX_MASK;=0D
+ Index2 =3D ((UINTN)Address >> 21) & PAGING_VTD_INDEX_MASK;=0D
+ Index1 =3D ((UINTN)Address >> 12) & PAGING_VTD_INDEX_MASK;=0D
+=0D
+ if (Is5LevelPaging) {=0D
+ L5PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ L5PageTable[Index5] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L5PageTable[Index5] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL5 PAGE FAIL (0x%x)!!!!!!\n=
", Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L5PageTable[Index5], SIZE_4KB=
);=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *=
)&L5PageTable[Index5], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=
=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L5PageTable[Index5], sizeof(=
L5PageTable[Index5]));=0D
+ }=0D
+ L4PageTable =3D (UINT64 *)(UINTN)(L5PageTable[Index5] & PAGING_4K_ADDR=
ESS_MASK_64);=0D
+ } else {=0D
+ L4PageTable =3D (UINT64 *)SecondLevelPagingEntry;=0D
+ }=0D
+=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ L4PageTable[Index4] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L4PageTable[Index4] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL4 PAGE FAIL (0x%x)!!!!!!\n",=
Index4));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L4PageTable[Index4], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L4PageTable[Index4], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L4PageTable[Index4], sizeof(L4=
PageTable[Index4]));=0D
+ }=0D
+=0D
+ L3PageTable =3D (UINT64 *)(UINTN)(L4PageTable[Index4] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ L3PageTable[Index3] =3D (UINT64)(UINTN)AllocateZeroPages (1);=0D
+ if (L3PageTable[Index3] =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"!!!!!! ALLOCATE LVL3 PAGE FAIL (0x%x, 0x%x)!!!!=
!!\n", Index4, Index3));=0D
+ ASSERT(FALSE);=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)L3PageTable[Index3], SIZE_4KB);=
=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L3PageTable[Index3], EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L3PageTable[Index3], sizeof(L3=
PageTable[Index3]));=0D
+ }=0D
+ if ((L3PageTable[Index3] & VTD_PG_PS) !=3D 0) {=0D
+ // 1G=0D
+ *PageAttribute =3D Page1G;=0D
+ return &L3PageTable[Index3];=0D
+ }=0D
+=0D
+ L2PageTable =3D (UINT64 *)(UINTN)(L3PageTable[Index3] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if (L2PageTable[Index2] =3D=3D 0) {=0D
+ L2PageTable[Index2] =3D Address & PAGING_2M_ADDRESS_MASK_64;=0D
+ SetSecondLevelPagingEntryAttribute ((VTD_SECOND_LEVEL_PAGING_ENTRY *)&=
L2PageTable[Index2], 0);=0D
+ L2PageTable[Index2] |=3D VTD_PG_PS;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)&L2PageTable[Index2], sizeof(L2=
PageTable[Index2]));=0D
+ }=0D
+ if ((L2PageTable[Index2] & VTD_PG_PS) !=3D 0) {=0D
+ // 2M=0D
+ *PageAttribute =3D Page2M;=0D
+ return &L2PageTable[Index2];=0D
+ }=0D
+=0D
+ // 4k=0D
+ L1PageTable =3D (UINT64 *)(UINTN)(L2PageTable[Index2] & PAGING_4K_ADDRES=
S_MASK_64);=0D
+ if ((L1PageTable[Index1] =3D=3D 0) && (Address !=3D 0)) {=0D
+ *PageAttribute =3D PageNone;=0D
+ return NULL;=0D
+ }=0D
+ *PageAttribute =3D Page4K;=0D
+ return &L1PageTable[Index1];=0D
+}=0D
+=0D
+/**=0D
+ Modify memory attributes of page entry.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+ @param[out] IsModified TRUE means page table modified. FALSE mean=
s page table not modified.=0D
+**/=0D
+VOID=0D
+ConvertSecondLevelPageEntryAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN UINT64 IoMmuAccess,=0D
+ OUT BOOLEAN *IsModified=0D
+ )=0D
+{=0D
+ UINT64 CurrentPageEntry;=0D
+ UINT64 NewPageEntry;=0D
+=0D
+ CurrentPageEntry =3D PageEntry->Uint64;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, IoMmuAccess);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry));=0D
+ NewPageEntry =3D PageEntry->Uint64;=0D
+ if (CurrentPageEntry !=3D NewPageEntry) {=0D
+ *IsModified =3D TRUE;=0D
+ DEBUG ((DEBUG_VERBOSE, "ConvertSecondLevelPageEntryAttribute 0x%lx", C=
urrentPageEntry));=0D
+ DEBUG ((DEBUG_VERBOSE, "->0x%lx\n", NewPageEntry));=0D
+ } else {=0D
+ *IsModified =3D FALSE;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ This function returns if there is need to split page entry.=0D
+=0D
+ @param[in] BaseAddress The base address to be checked.=0D
+ @param[in] Length The length to be checked.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+=0D
+ @retval SplitAttributes on if there is need to split page entry.=0D
+**/=0D
+PAGE_ATTRIBUTE=0D
+NeedSplitPage (=0D
+ IN PHYSICAL_ADDRESS BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN PAGE_ATTRIBUTE PageAttribute=0D
+ )=0D
+{=0D
+ UINT64 PageEntryLength;=0D
+=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+=0D
+ if (((BaseAddress & (PageEntryLength - 1)) =3D=3D 0) && (Length >=3D Pag=
eEntryLength)) {=0D
+ return PageNone;=0D
+ }=0D
+=0D
+ if (((BaseAddress & PAGING_2M_MASK) !=3D 0) || (Length < SIZE_2MB)) {=0D
+ return Page4K;=0D
+ }=0D
+=0D
+ return Page2M;=0D
+}=0D
+=0D
+/**=0D
+ This function splits one page entry to small page entries.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] PageEntry The page entry to be splitted.=0D
+ @param[in] PageAttribute The page attribute of the page entry.=0D
+ @param[in] SplitAttribute How to split the page entry.=0D
+=0D
+ @retval RETURN_SUCCESS The page entry is splitted.=0D
+ @retval RETURN_UNSUPPORTED The page entry does not support to be =
splitted.=0D
+ @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.=0D
+**/=0D
+RETURN_STATUS=0D
+SplitSecondLevelPage (=0D
+ IN UINTN VtdIndex,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry,=0D
+ IN PAGE_ATTRIBUTE PageAttribute,=0D
+ IN PAGE_ATTRIBUTE SplitAttribute=0D
+ )=0D
+{=0D
+ UINT64 BaseAddress;=0D
+ UINT64 *NewPageEntry;=0D
+ UINTN Index;=0D
+=0D
+ ASSERT (PageAttribute =3D=3D Page2M || PageAttribute =3D=3D Page1G);=0D
+=0D
+ if (PageAttribute =3D=3D Page2M) {=0D
+ //=0D
+ // Split 2M to 4K=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page4K);=0D
+ if (SplitAttribute =3D=3D Page4K) {=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_2M_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_4KB * Index) | (PageEn=
try->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else if (PageAttribute =3D=3D Page1G) {=0D
+ //=0D
+ // Split 1G to 2M=0D
+ // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K =
to get more compact page table.=0D
+ //=0D
+ ASSERT (SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K);=
=0D
+ if ((SplitAttribute =3D=3D Page2M || SplitAttribute =3D=3D Page4K)) {=
=0D
+ NewPageEntry =3D AllocateZeroPages (1);=0D
+ DEBUG ((DEBUG_VERBOSE, "Split - 0x%x\n", NewPageEntry));=0D
+ if (NewPageEntry =3D=3D NULL) {=0D
+ return RETURN_OUT_OF_RESOURCES;=0D
+ }=0D
+ BaseAddress =3D PageEntry->Uint64 & PAGING_1G_ADDRESS_MASK_64;=0D
+ for (Index =3D 0; Index < SIZE_4KB / sizeof(UINT64); Index++) {=0D
+ NewPageEntry[Index] =3D (BaseAddress + SIZE_2MB * Index) | VTD_PG_=
PS | (PageEntry->Uint64 & PAGE_PROGATE_BITS);=0D
+ }=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)NewPageEntry, SIZE_4KB);=0D
+=0D
+ PageEntry->Uint64 =3D (UINT64)(UINTN)NewPageEntry;=0D
+ SetSecondLevelPagingEntryAttribute (PageEntry, EDKII_IOMMU_ACCESS_RE=
AD | EDKII_IOMMU_ACCESS_WRITE);=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)PageEntry, sizeof(*PageEntry)=
);=0D
+ return RETURN_SUCCESS;=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ } else {=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory on second level page entry=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetSecondLevelPagingAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *PageEntry;=0D
+ PAGE_ATTRIBUTE PageAttribute;=0D
+ UINTN PageEntryLength;=0D
+ PAGE_ATTRIBUTE SplitAttribute;=0D
+ EFI_STATUS Status;=0D
+ BOOLEAN IsEntryModified;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetSecondLevelPagingAttribute (%d) (0x%016lx - 0x=
%016lx : %x) \n", VtdIndex, BaseAddress, Length, IoMmuAccess));=0D
+ DEBUG ((DEBUG_VERBOSE," SecondLevelPagingEntry Base - 0x%x\n", SecondLe=
velPagingEntry));=0D
+=0D
+ if (BaseAddress !=3D ALIGN_VALUE(BaseAddress, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+ if (Length !=3D ALIGN_VALUE(Length, SIZE_4KB)) {=0D
+ DEBUG ((DEBUG_ERROR, "SetSecondLevelPagingAttribute - Invalid Alignmen=
t\n"));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ while (Length !=3D 0) {=0D
+ PageEntry =3D GetSecondLevelPageTableEntry (VtdIndex, SecondLevelPagin=
gEntry, BaseAddress, mVtdUnitInformation[VtdIndex].Is5LevelPaging, &PageAtt=
ribute);=0D
+ if (PageEntry =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR, "PageEntry - NULL\n"));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ PageEntryLength =3D PageAttributeToLength (PageAttribute);=0D
+ SplitAttribute =3D NeedSplitPage (BaseAddress, Length, PageAttribute);=
=0D
+ if (SplitAttribute =3D=3D PageNone) {=0D
+ ConvertSecondLevelPageEntryAttribute (VtdIndex, PageEntry, IoMmuAcce=
ss, &IsEntryModified);=0D
+ if (IsEntryModified) {=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ }=0D
+ //=0D
+ // Convert success, move to next=0D
+ //=0D
+ BaseAddress +=3D PageEntryLength;=0D
+ Length -=3D PageEntryLength;=0D
+ } else {=0D
+ Status =3D SplitSecondLevelPage (VtdIndex, PageEntry, PageAttribute,=
SplitAttribute);=0D
+ if (RETURN_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));=0D
+ return RETURN_UNSUPPORTED;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyPages =3D TRUE;=0D
+ //=0D
+ // Just split current page=0D
+ // Convert success in next around=0D
+ //=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd eng=
ine.=0D
+ @param[in] DomainIdentifier The domain ID of the source.=0D
+ @param[in] SecondLevelPagingEntry The second level paging entry in VTd=
table for the device.=0D
+ @param[in] BaseAddress The base of device memory address to=
be used as the DMA memory.=0D
+ @param[in] Length The length of device memory address =
to be used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetPageAttribute (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINT16 DomainIdentifier,=0D
+ IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ Status =3D EFI_NOT_FOUND;=0D
+ if (SecondLevelPagingEntry !=3D NULL) {=0D
+ Status =3D SetSecondLevelPagingAttribute (VtdIndex, DomainIdentifier, =
SecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);=0D
+ }=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Set VTd attribute for a system memory.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+ @param[in] BaseAddress The base of device memory address to be us=
ed as the DMA memory.=0D
+ @param[in] Length The length of device memory address to be =
used as the DMA memory.=0D
+ @param[in] IoMmuAccess The IOMMU access.=0D
+=0D
+ @retval EFI_SUCCESS The IoMmuAccess is set for the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligne=
d.=0D
+ @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.=0D
+ @retval EFI_INVALID_PARAMETER Length is 0.=0D
+ @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combinat=
ion of access.=0D
+ @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not suppor=
ted by the IOMMU.=0D
+ @retval EFI_UNSUPPORTED The IOMMU does not support the memory ran=
ge specified by BaseAddress and Length.=0D
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available =
to modify the IOMMU access.=0D
+ @retval EFI_DEVICE_ERROR The IOMMU device reported an error while =
attempting the operation.=0D
+**/=0D
+EFI_STATUS=0D
+SetAccessAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId,=0D
+ IN UINT64 BaseAddress,=0D
+ IN UINT64 Length,=0D
+ IN UINT64 IoMmuAccess=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ EFI_STATUS Status;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+ UINTN PciDataIndex;=0D
+ UINT16 DomainIdentifier;=0D
+=0D
+ SecondLevelPagingEntry =3D NULL;=0D
+=0D
+ DEBUG ((DEBUG_VERBOSE,"SetAccessAttribute (S%04x B%02x D%02x F%02x) (0x%=
016lx - 0x%08x, %x)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function, BaseAddress, (UINTN)Length, IoMmuAccess));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"SetAccessAttribute - Pci device (S%04x B%02x D%02=
x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, S=
ourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ PciDataIndex =3D GetPciDataIndex (VtdIndex, Segment, SourceId);=0D
+ mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDeviceData[PciDataIndex]=
.AccessCount++;=0D
+ //=0D
+ // DomainId should not be 0.=0D
+ //=0D
+ DomainIdentifier =3D (UINT16)(PciDataIndex + 1);=0D
+=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ if (ExtContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT3=
2) Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT3=
2) RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtC=
ontextEntry));=0D
+ VtdLibDumpDmarExtContextEntryTable (NULL, NULL, mVtdUnitInformation[=
VtdIndex].ExtRootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=
=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(ExtCont=
extEntry->Bits.SecondLevelPageTranslationPointerLo, ExtContextEntry->Bits.S=
econdLevelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ if (ContextEntry->Bits.Present =3D=3D 0) {=0D
+ SecondLevelPagingEntry =3D CreateSecondLevelPagingEntry (VtdIndex, 0=
, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x) New\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, Sour=
ceId.Bits.Device, SourceId.Bits.Function));=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12)=
;=0D
+=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) =
Pt;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) =
RShiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D DomainIdentifier;=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*Context=
Entry));=0D
+ VtdLibDumpDmarContextEntryTable (NULL, NULL, mVtdUnitInformation[Vtd=
Index].RootEntryTable, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ mVtdUnitInformation[VtdIndex].HasDirtyContext =3D TRUE;=0D
+ } else {=0D
+ SecondLevelPagingEntry =3D (VOID *)(UINTN)VTD_64BITS_ADDRESS(Context=
Entry->Bits.SecondLevelPageTranslationPointerLo, ContextEntry->Bits.SecondL=
evelPageTranslationPointerHi);=0D
+ DEBUG ((DEBUG_VERBOSE,"SecondLevelPagingEntry - 0x%x (S%04x B%02x D%=
02x F%02x)\n", SecondLevelPagingEntry, Segment, SourceId.Bits.Bus, SourceId=
.Bits.Device, SourceId.Bits.Function));=0D
+ }=0D
+ }=0D
+=0D
+ //=0D
+ // Do not update FixedSecondLevelPagingEntry=0D
+ //=0D
+ if (SecondLevelPagingEntry !=3D mVtdUnitInformation[VtdIndex].FixedSecon=
dLevelPagingEntry) {=0D
+ Status =3D SetPageAttribute (=0D
+ VtdIndex,=0D
+ DomainIdentifier,=0D
+ SecondLevelPagingEntry,=0D
+ BaseAddress,=0D
+ Length,=0D
+ IoMmuAccess=0D
+ );=0D
+ if (EFI_ERROR (Status)) {=0D
+ DEBUG ((DEBUG_ERROR,"SetPageAttribute - %r\n", Status));=0D
+ return Status;=0D
+ }=0D
+ }=0D
+=0D
+ InvalidatePageEntry (VtdIndex);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Always enable the VTd page attribute for the device.=0D
+=0D
+ @param[in] Segment The Segment used to identify a VTd engine.=
=0D
+ @param[in] SourceId The SourceId used to identify a VTd engine=
and table entry.=0D
+=0D
+ @retval EFI_SUCCESS The VTd entry is updated to always enable =
all DMA access for the specific device.=0D
+**/=0D
+EFI_STATUS=0D
+AlwaysEnablePageAttribute (=0D
+ IN UINT16 Segment,=0D
+ IN VTD_SOURCE_ID SourceId=0D
+ )=0D
+{=0D
+ UINTN VtdIndex;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_CONTEXT_ENTRY *ContextEntry;=0D
+ VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;=0D
+ UINT64 Pt;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"AlwaysEnablePageAttribute (S%04x B%02x D%02x F%02x)\=
n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Functio=
n));=0D
+=0D
+ VtdIndex =3D FindVtdIndexByPciDevice (Segment, SourceId, &ExtContextEntr=
y, &ContextEntry);=0D
+ if (VtdIndex =3D=3D (UINTN)-1) {=0D
+ DEBUG ((DEBUG_ERROR,"AlwaysEnablePageAttribute - Pci device (S%04x B%0=
2x D%02x F%02x) not found!\n", Segment, SourceId.Bits.Bus, SourceId.Bits.De=
vice, SourceId.Bits.Function));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D=3D 0) =
{=0D
+ DEBUG((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex));=
=0D
+ mVtdUnitInformation[VtdIndex].FixedSecondLevelPagingEntry =3D CreateSe=
condLevelPagingEntry (VtdIndex, EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCES=
S_WRITE, mVtdUnitInformation[VtdIndex].Is5LevelPaging);=0D
+ }=0D
+=0D
+ SecondLevelPagingEntry =3D mVtdUnitInformation[VtdIndex].FixedSecondLeve=
lPagingEntry;=0D
+ Pt =3D (UINT64)RShiftU64 ((UINT64)(UINTN)SecondLevelPagingEntry, 12);=0D
+ if (ExtContextEntry !=3D NULL) {=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32)=
Pt;=0D
+ ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32)=
RShiftU64(Pt, 20);=0D
+ ExtContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdU=
nitInformation[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ExtContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ExtContextEntry, sizeof(*ExtCon=
textEntry));=0D
+ } else if (ContextEntry !=3D NULL) {=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerLo =3D (UINT32) Pt=
;=0D
+ ContextEntry->Bits.SecondLevelPageTranslationPointerHi =3D (UINT32) RS=
hiftU64(Pt, 20);=0D
+ ContextEntry->Bits.DomainIdentifier =3D ((1 << (UINT8)((UINTN)mVtdUnit=
Information[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);=0D
+ ContextEntry->Bits.Present =3D 1;=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)ContextEntry, sizeof(*ContextEn=
try));=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Tran=
slationTableEx.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDx=
e/TranslationTableEx.c
new file mode 100644
index 000000000..c07afaf2b
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/Translation=
TableEx.c
@@ -0,0 +1,108 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+/**=0D
+ Create extended context entry.=0D
+=0D
+ @param[in] VtdIndex The index of the VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The extended context entry is created.=0D
+ @retval EFI_OUT_OF_RESOURCE No enough resource to create extended conte=
xt entry.=0D
+**/=0D
+EFI_STATUS=0D
+CreateExtContextEntry (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ VOID *Buffer;=0D
+ UINTN RootPages;=0D
+ UINTN ContextPages;=0D
+ VTD_EXT_ROOT_ENTRY *ExtRootEntry;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntryTable;=0D
+ VTD_EXT_CONTEXT_ENTRY *ExtContextEntry;=0D
+ VTD_SOURCE_ID *PciSourceId;=0D
+ VTD_SOURCE_ID SourceId;=0D
+ UINTN MaxBusNumber;=0D
+ UINTN EntryTablePages;=0D
+=0D
+ MaxBusNumber =3D 0;=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+ if (PciSourceId->Bits.Bus > MaxBusNumber) {=0D
+ MaxBusNumber =3D PciSourceId->Bits.Bus;=0D
+ }=0D
+ }=0D
+ DEBUG ((DEBUG_INFO," MaxBusNumber - 0x%x\n", MaxBusNumber));=0D
+=0D
+ RootPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_=
ENTRY_NUMBER);=0D
+ ContextPages =3D EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD=
_CONTEXT_ENTRY_NUMBER);=0D
+ EntryTablePages =3D RootPages + ContextPages * (MaxBusNumber + 1);=0D
+ Buffer =3D AllocateZeroPages (EntryTablePages);=0D
+ if (Buffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_INFO,"Could not Alloc Root Entry Table.. \n"));=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ mVtdUnitInformation[VtdIndex].ExtRootEntryTable =3D (VTD_EXT_ROOT_ENTRY =
*)Buffer;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (RootPages);=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitInformation[VtdIndex].PciDeviceInfo->P=
ciDeviceDataNumber; Index++) {=0D
+ PciSourceId =3D &mVtdUnitInformation[VtdIndex].PciDeviceInfo->PciDevic=
eData[Index].PciSourceId;=0D
+=0D
+ SourceId.Bits.Bus =3D PciSourceId->Bits.Bus;=0D
+ SourceId.Bits.Device =3D PciSourceId->Bits.Device;=0D
+ SourceId.Bits.Function =3D PciSourceId->Bits.Function;=0D
+=0D
+ ExtRootEntry =3D &mVtdUnitInformation[VtdIndex].ExtRootEntryTable[Sour=
ceId.Index.RootIndex];=0D
+ if (ExtRootEntry->Bits.LowerPresent =3D=3D 0) {=0D
+ ExtRootEntry->Bits.LowerContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12);=0D
+ ExtRootEntry->Bits.LowerContextTablePointerHi =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 32);=0D
+ ExtRootEntry->Bits.LowerPresent =3D 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerLo =3D (UINT32) RShiftU6=
4 ((UINT64)(UINTN)Buffer, 12) + 1;=0D
+ ExtRootEntry->Bits.UpperContextTablePointerHi =3D (UINT32) RShiftU6=
4 (RShiftU64 ((UINT64)(UINTN)Buffer, 12) + 1, 20);=0D
+ ExtRootEntry->Bits.UpperPresent =3D 1;=0D
+ Buffer =3D (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);=0D
+ }=0D
+=0D
+ ExtContextEntryTable =3D (VTD_EXT_CONTEXT_ENTRY *)(UINTN)VTD_64BITS_AD=
DRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.Low=
erContextTablePointerHi) ;=0D
+ ExtContextEntry =3D &ExtContextEntryTable[SourceId.Index.ContextIndex]=
;=0D
+ ExtContextEntry->Bits.TranslationType =3D 0;=0D
+ ExtContextEntry->Bits.FaultProcessingDisable =3D 0;=0D
+ ExtContextEntry->Bits.Present =3D 0;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DOMAIN: S%04x, B%02x D%02x F%02x\n", mVtdUnitInfor=
mation[VtdIndex].Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId=
.Bits.Function));=0D
+=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=
=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D TRUE;=0D
+ if ((mAcpiDmarTable->HostAddressWidth <=3D 48) &&=0D
+ ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) !=3D 0=
)) {=0D
+ mVtdUnitInformation[VtdIndex].Is5LevelPaging =3D FALSE;=0D
+ }=0D
+ } else if ((mVtdUnitInformation[VtdIndex].CapReg.Bits.SAGAW & BIT2) =
=3D=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type is not supported on VTD %d=
!!!!\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].Is5LevelPaging) {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x3;=0D
+ DEBUG((DEBUG_INFO, "Using 5-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ } else {=0D
+ ExtContextEntry->Bits.AddressWidth =3D 0x2;=0D
+ DEBUG((DEBUG_INFO, "Using 4-level page-table on VTD %d\n", VtdIndex)=
);=0D
+ }=0D
+=0D
+=0D
+ }=0D
+=0D
+ FlushPageTableMemory (VtdIndex, (UINTN)mVtdUnitInformation[VtdIndex].Ext=
RootEntryTable, EFI_PAGES_TO_SIZE(EntryTablePages));=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdR=
eg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
new file mode 100644
index 000000000..56d621ff6
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdCoreDxe/VtdReg.c
@@ -0,0 +1,759 @@
+/** @file=0D
+=0D
+ Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "DmaProtection.h"=0D
+=0D
+#define VTD_CAP_REG_NFR_MAX (256)=0D
+=0D
+UINTN mVtdUnitNumber =3D 0;=0D
+VTD_UNIT_INFORMATION *mVtdUnitInformation =3D NULL;=0D
+VTD_REGESTER_INFO *mVtdRegsInfoBuffer =3D NULL;=0D
+=0D
+BOOLEAN mVtdEnabled;=0D
+=0D
+/**=0D
+ Flush VTD page table and context table memory.=0D
+=0D
+ This action is to make sure the IOMMU engine can get final data in memor=
y.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] Base The base address of memory to be flushed.=
=0D
+ @param[in] Size The size of memory in bytes to be flushed.=
=0D
+**/=0D
+VOID=0D
+FlushPageTableMemory (=0D
+ IN UINTN VtdIndex,=0D
+ IN UINTN Base,=0D
+ IN UINTN Size=0D
+ )=0D
+{=0D
+ if (mVtdUnitInformation[VtdIndex].ECapReg.Bits.C =3D=3D 0) {=0D
+ WriteBackDataCacheRange ((VOID *)Base, Size);=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Perpare cache invalidation interface.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval EFI_UNSUPPORTED Invalidation method is not supported.=0D
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.=0D
+**/=0D
+EFI_STATUS=0D
+PerpareCacheInvalidationInterface (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT32 Reg32;=0D
+ VTD_IQA_REG IqaReg;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+ UINTN VtdUnitBaseAddress;=0D
+=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[VtdIndex];=0D
+ VtdUnitBaseAddress =3D VtdUnitInfo->VtdUnitBaseAddress;=0D
+=0D
+ if (VtdUnitInfo->VerReg.Bits.Major <=3D 5) {=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for eng=
ine [%d]\n", VtdIndex));=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ if (VtdUnitInfo->ECapReg.Bits.QI =3D=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations i=
nterface for engine [%d]\n", VtdIndex));=0D
+ return EFI_UNSUPPORTED;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 1;=0D
+ DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [%d]\n=
", VtdIndex));=0D
+=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ if ((Reg32 & B_GSTS_REG_QIES) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"Queued Invalidation Interface was enabled.\n"));=
=0D
+ Reg32 &=3D (~B_GSTS_REG_QIES);=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) !=3D 0);=0D
+ }=0D
+=0D
+ //=0D
+ // Initialize the Invalidation Queue Tail Register to zero.=0D
+ //=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);=0D
+=0D
+ //=0D
+ // Setup the IQ address, size and descriptor width through the Invalidat=
ion Queue Address Register=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ VtdUnitInfo->QiDescBufferSize =3D (sizeof (QI_256_DESC) * ((UINTN) 1 <=
< (VTD_INVALIDATION_QUEUE_SIZE + 7)));=0D
+ VtdUnitInfo->QiDescBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (VtdUni=
tInfo->QiDescBufferSize));=0D
+ if (VtdUnitInfo->QiDescBuffer =3D=3D NULL) {=0D
+ DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"))=
;=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ERROR_OUT=
_OF_RESOURCES, VtdUnitBaseAddress);=0D
+ return EFI_OUT_OF_RESOURCES;=0D
+ }=0D
+ }=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Invalidation Queue Buffer Size : %d\n", VtdUnitInfo=
->QiDescBufferSize));=0D
+ //=0D
+ // 4KB Aligned address=0D
+ //=0D
+ IqaReg.Uint64 =3D (UINT64) (UINTN) VtdUnitInfo->QiDescBuffer;=0D
+ IqaReg.Bits.DW =3D VTD_QUEUED_INVALIDATION_DESCRIPTOR_WIDTH;=0D
+ IqaReg.Bits.QS =3D VTD_INVALIDATION_QUEUE_SIZE;=0D
+ MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, IqaReg.Uint64);=0D
+ IqaReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_IQA_REG);=0D
+ DEBUG ((DEBUG_INFO, "IQA_REG =3D 0x%lx, IQH_REG =3D 0x%lx\n", IqaReg.Uin=
t64, MmioRead64 (VtdUnitBaseAddress + R_IQH_REG)));=0D
+=0D
+ //=0D
+ // Enable the queued invalidation interface through the Global Command R=
egister.=0D
+ // When enabled, hardware sets the QIES field in the Global Status Regis=
ter.=0D
+ //=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ Reg32 |=3D B_GMCD_REG_QIE;=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);=0D
+ DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG =3D =
0x%x\n", Reg32));=0D
+ do {=0D
+ Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);=0D
+ } while ((Reg32 & B_GSTS_REG_QIES) =3D=3D 0);=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_ENABLE, VtdUn=
itBaseAddress);=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Submit the queued invalidation descriptor to the remapping=0D
+ hardware unit and wait for its completion.=0D
+=0D
+ @param[in] VtdUnitBaseAddress The base address of the VTd engine.=0D
+ @param[in] Desc The invalidate descriptor=0D
+=0D
+ @retval EFI_SUCCESS The operation was successful.=0D
+ @retval RETURN_DEVICE_ERROR A fault is detected.=0D
+ @retval EFI_INVALID_PARAMETER Parameter is invalid.=0D
+**/=0D
+EFI_STATUS=0D
+SubmitQueuedInvalidationDescriptor (=0D
+ IN UINTN VtdUnitBaseAddress,=0D
+ IN QI_256_DESC *Desc=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ VTD_REGESTER_QI_INFO RegisterQi;=0D
+=0D
+ Status =3D VtdLibSubmitQueuedInvalidationDescriptor (VtdUnitBaseAddress,=
Desc, FALSE);=0D
+ if (Status =3D=3D EFI_DEVICE_ERROR) {=0D
+ RegisterQi.BaseAddress =3D VtdUnitBaseAddress;=0D
+ RegisterQi.FstsReg =3D MmioRead32 (VtdUnitBaseAddress + R_FSTS_REG=
);;=0D
+ RegisterQi.IqercdReg =3D MmioRead64 (VtdUnitBaseAddress + R_IQERCD_R=
EG);=0D
+ VTdLogAddDataEvent (VTDLOG_PEI_REGISTER, VTDLOG_REGISTER_QI, &Register=
Qi, sizeof (VTD_REGESTER_QI_INFO));=0D
+=0D
+ MmioWrite32 (VtdUnitBaseAddress + R_FSTS_REG, RegisterQi.FstsReg & (B_=
FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE));=0D
+ }=0D
+=0D
+ return Status;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd context cache.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateContextCache (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ R_CCMD_REG);=0D
+ if ((Reg64 & B_CCMD_REG_ICC) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC i=
s set for VTD(%d)\n",VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));=0D
+ Reg64 |=3D (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_CCMD=
_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + R_CCMD_REG);=0D
+ } while ((Reg64 & B_CCMD_REG_ICC) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_CC_FM(0) | QI_CC_SID(0) | QI_CC_DID(0) | QI_CC=
_GRAN(1) | QI_CC_TYPE;=0D
+ QiDesc.Uint64[1] =3D 0;=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalidate VTd IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateIOTLB (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+ QI_256_DESC QiDesc;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].EnableQueuedInvalidation =3D=3D 0) {=0D
+ //=0D
+ // Register-based Invalidation=0D
+ //=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
+ (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=0D
+ if ((Reg64 & B_IOTLB_REG_IVT) !=3D 0) {=0D
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set =
for VTD(%d)\n", VtdIndex));=0D
+ return EFI_DEVICE_ERROR;=0D
+ }=0D
+=0D
+ Reg64 &=3D ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));=0D
+ Reg64 |=3D (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + (mVtdU=
nitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);=0D
+=0D
+ do {=0D
+ Reg64 =3D MmioRead64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddre=
ss + (mVtdUnitInformation[VtdIndex].ECapReg.Bits.IRO * 16) + R_IOTLB_REG);=
=0D
+ } while ((Reg64 & B_IOTLB_REG_IVT) !=3D 0);=0D
+ } else {=0D
+ //=0D
+ // Queued Invalidation=0D
+ //=0D
+ QiDesc.Uint64[0] =3D QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(mVtd=
UnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(mVt=
dUnitInformation[VtdIndex].CapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TY=
PE;=0D
+ QiDesc.Uint64[1] =3D QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0=
);=0D
+ QiDesc.Uint64[2] =3D 0;=0D
+ QiDesc.Uint64[3] =3D 0;=0D
+=0D
+ return SubmitQueuedInvalidationDescriptor(mVtdUnitInformation[VtdIndex=
].VtdUnitBaseAddress, &QiDesc);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Invalid VTd global IOTLB.=0D
+=0D
+ @param[in] VtdIndex The index of VTd engine.=0D
+=0D
+ @retval EFI_SUCCESS VTd global IOTLB is invalidated.=0D
+ @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.=0D
+**/=0D
+EFI_STATUS=0D
+InvalidateVtdIOTLBGlobal (=0D
+ IN UINTN VtdIndex=0D
+ )=0D
+{=0D
+ if (!mVtdEnabled) {=0D
+ return EFI_SUCCESS;=0D
+ }=0D
+=0D
+ DEBUG((DEBUG_VERBOSE, "InvalidateVtdIOTLBGlobal(%d)\n", VtdIndex));=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress=
);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext) {=0D
+ InvalidateContextCache (VtdIndex);=0D
+ }=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ if (mVtdUnitInformation[VtdIndex].HasDirtyContext || mVtdUnitInformation=
[VtdIndex].HasDirtyPages) {=0D
+ InvalidateIOTLB (VtdIndex);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Prepare VTD configuration.=0D
+**/=0D
+VOID=0D
+PrepareVtdConfig (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN DomainNumber;=0D
+ EFI_STATUS Status;=0D
+=0D
+ if (mVtdRegsInfoBuffer =3D=3D NULL) {=0D
+ mVtdRegsInfoBuffer =3D AllocateZeroPool (sizeof (VTD_REGESTER_INFO) + =
sizeof (VTD_UINT128) * VTD_CAP_REG_NFR_MAX);=0D
+ ASSERT (mVtdRegsInfoBuffer !=3D NULL);=0D
+ }=0D
+=0D
+ //=0D
+ // Dump VTd error before DXE phase=0D
+ //=0D
+ DumpVtdIfError ();=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ DEBUG ((DEBUG_INFO, "Dump VTd Capability (%d)\n", Index));=0D
+ mVtdUnitInformation[Index].VerReg.Uint32 =3D MmioRead32 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_VER_REG);=0D
+ DumpVtdVerRegs (&mVtdUnitInformation[Index].VerReg);=0D
+ mVtdUnitInformation[Index].CapReg.Uint64 =3D MmioRead64 (mVtdUnitInfor=
mation[Index].VtdUnitBaseAddress + R_CAP_REG);=0D
+ DumpVtdCapRegs (&mVtdUnitInformation[Index].CapReg);=0D
+ mVtdUnitInformation[Index].ECapReg.Uint64 =3D MmioRead64 (mVtdUnitInfo=
rmation[Index].VtdUnitBaseAddress + R_ECAP_REG);=0D
+ DumpVtdECapRegs (&mVtdUnitInformation[Index].ECapReg);=0D
+=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SLLPS & BIT0) =3D=3D 0) {=
=0D
+ DEBUG((DEBUG_WARN, "!!!! 2MB super page is not supported on VTD %d !=
!!!\n", Index));=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT3) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & BIT2) !=3D 0) {=0D
+ DEBUG((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index))=
;=0D
+ }=0D
+ if ((mVtdUnitInformation[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) =3D=
=3D 0) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on V=
TD %d !!!!\n", Index, mVtdUnitInformation[Index].CapReg.Bits.SAGAW));=0D
+ return ;=0D
+ }=0D
+=0D
+ DomainNumber =3D (UINTN)1 << (UINT8)((UINTN)mVtdUnitInformation[Index]=
.CapReg.Bits.ND * 2 + 4);=0D
+ if (mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumber >=3D=
DomainNumber) {=0D
+ DEBUG((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >=3D DomainNumber(=
0x%x) !!!!\n", mVtdUnitInformation[Index].PciDeviceInfo->PciDeviceDataNumbe=
r, DomainNumber));=0D
+ return ;=0D
+ }=0D
+=0D
+ Status =3D PerpareCacheInvalidationInterface(Index);=0D
+ if (EFI_ERROR (Status)) {=0D
+ ASSERT(FALSE);=0D
+ return;=0D
+ }=0D
+ }=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Disable PMR in all VTd engine.=0D
+**/=0D
+VOID=0D
+DisablePmr (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ EFI_STATUS Status;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"DisablePmr\n"));=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ Status =3D VtdLibDisablePmr (mVtdUnitInformation[Index].VtdUnitBaseAdd=
ress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_PMR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, Status);=0D
+ }=0D
+=0D
+ return ;=0D
+}=0D
+=0D
+/**=0D
+ Update Root Table Address Register=0D
+=0D
+ @param[in] VtdIndex The index used to identify a VTd engine.=0D
+ @param[in] EnableADM TRUE - Enable ADM in TTM bits=0D
+**/=0D
+VOID=0D
+UpdateRootTableAddressRegister (=0D
+ IN UINTN VtdIndex,=0D
+ IN BOOLEAN EnableADM=0D
+ )=0D
+{=0D
+ UINT64 Reg64;=0D
+=0D
+ if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable !=3D NULL) {=0D
+ DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Vt=
dIndex].ExtRootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTab=
le | (EnableADM ? V_RTADDR_REG_TTM_ADM : BIT11);=0D
+ } else {=0D
+ DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[VtdIn=
dex].RootEntryTable));=0D
+ Reg64 =3D (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable =
| (EnableADM ? V_RTADDR_REG_TTM_ADM : 0);=0D
+ }=0D
+ MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR=
_REG, Reg64);=0D
+}=0D
+=0D
+/**=0D
+ Enable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is enabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.=0D
+**/=0D
+EFI_STATUS=0D
+EnableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN VtdUnitBaseAddress;=0D
+ BOOLEAN TEWasEnabled;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitBaseAddress =3D mVtdUnitInformation[Index].VtdUnitBaseAddress;=
=0D
+ DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] BAR [0x%x]\n", =
Index, VtdUnitBaseAddress));=0D
+=0D
+ //=0D
+ // Check TE was enabled or not.=0D
+ //=0D
+ TEWasEnabled =3D ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GS=
TS_REG_TE) =3D=3D B_GSTS_REG_TE);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ //=0D
+ // For implementations reporting Enhanced SRTP Support (ESRTPS) fiel=
d as=0D
+ // Clear in the Capability register, software must not modify this f=
ield while=0D
+ // DMA remapping is active (TES=3D1 in Global Status register).=0D
+ //=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable ADM=0D
+ //=0D
+ UpdateRootTableAddressRegister (Index, TRUE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+=0D
+ DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_T=
E);=0D
+=0D
+ } else {=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Write Buffer Flush before invalidation=0D
+ //=0D
+ VtdLibFlushWriteBuffer (VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Invalidate the context cache=0D
+ //=0D
+ InvalidateContextCache (Index);=0D
+=0D
+ //=0D
+ // Invalidate the IOTLB cache=0D
+ //=0D
+ InvalidateIOTLB (Index);=0D
+=0D
+ if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS =3D=
=3D 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {=0D
+ if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS =3D=3D 0) {=0D
+ VtdLibClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_R=
EG_TE);=0D
+ }=0D
+=0D
+ UpdateRootTableAddressRegister (Index, FALSE);=0D
+=0D
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n=
"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_S=
RTP);=0D
+ }=0D
+=0D
+ //=0D
+ // Enable VTd=0D
+ //=0D
+ DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));=0D
+ VtdLibSetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE)=
;=0D
+=0D
+ DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));=0D
+=0D
+ VTdLogAddEvent (VTDLOG_DXE_ENABLE_DMAR, mVtdUnitInformation[Index].Vtd=
UnitBaseAddress, 0);=0D
+ }=0D
+=0D
+ //=0D
+ // Need disable PMR, since we already setup translation table.=0D
+ //=0D
+ DisablePmr ();=0D
+=0D
+ mVtdEnabled =3D TRUE;=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Disable DMAR translation.=0D
+=0D
+ @retval EFI_SUCCESS DMAR translation is disabled.=0D
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.=0D
+**/=0D
+EFI_STATUS=0D
+DisableDmar (=0D
+ VOID=0D
+ )=0D
+{=0D
+ UINTN Index;=0D
+ UINTN SubIndex;=0D
+ VTD_UNIT_INFORMATION *VtdUnitInfo;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+=0D
+ VtdLibDisableDmar (VtdUnitInfo->VtdUnitBaseAddress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_DISABLE_DMAR, VtdUnitInfo->VtdUnitBaseAddre=
ss, 0);=0D
+=0D
+ if (VtdUnitInfo->EnableQueuedInvalidation !=3D 0) {=0D
+ //=0D
+ // Disable queued invalidation interface.=0D
+ //=0D
+ VtdLibDisableQueuedInvalidationInterface (VtdUnitInfo->VtdUnitBaseAd=
dress);=0D
+ VTdLogAddEvent (VTDLOG_DXE_QUEUED_INVALIDATION, VTD_LOG_QI_DISABLE, =
VtdUnitInfo->VtdUnitBaseAddress);=0D
+=0D
+ //=0D
+ // Free descriptor queue memory=0D
+ //=0D
+ if (VtdUnitInfo->QiDescBuffer !=3D NULL) {=0D
+ FreePages(VtdUnitInfo->QiDescBuffer, EFI_SIZE_TO_PAGES (VtdUnitInf=
o->QiDescBufferSize));=0D
+ VtdUnitInfo->QiDescBuffer =3D NULL;=0D
+ VtdUnitInfo->QiDescBufferSize =3D 0;=0D
+ }=0D
+=0D
+ VtdUnitInfo->EnableQueuedInvalidation =3D 0;=0D
+ }=0D
+ }=0D
+=0D
+ mVtdEnabled =3D FALSE;=0D
+=0D
+ for (Index =3D 0; Index < mVtdUnitNumber; Index++) {=0D
+ VtdUnitInfo =3D &mVtdUnitInformation[Index];=0D
+ DEBUG((DEBUG_INFO, "engine [%d] access\n", Index));=0D
+ for (SubIndex =3D 0; SubIndex < VtdUnitInfo->PciDeviceInfo->PciDeviceD=
ataNumber; SubIndex++) {=0D
+ DEBUG ((DEBUG_INFO, " PCI S%04X B%02x D%02x F%02x - %d\n",=0D
+ VtdUnitInfo->Segment,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Bus,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Device,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].PciSourceId.Bits.=
Function,=0D
+ VtdUnitInfo->PciDeviceInfo->PciDeviceData[Index].AccessCount=0D
+ ));=0D
+ }=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd version registers.=0D
+=0D
+ @param[in] VerReg The version register.=0D
+**/=0D
+VOID=0D
+DumpVtdVerRegs (=0D
+ IN VTD_VER_REG *VerReg=0D
+ )=0D
+{=0D
+ DEBUG ((DEBUG_INFO, " VerReg - 0x%x\n", VerReg->Uint32));=0D
+ DEBUG ((DEBUG_INFO, " Major - 0x%x\n", VerReg->Bits.Major));=0D
+ DEBUG ((DEBUG_INFO, " Minor - 0x%x\n", VerReg->Bits.Minor));=0D
+}=0D
+=0D
+/**=0D
+ Dump VTd capability registers.=0D
+=0D
+ @param[in] CapReg The capability register.=0D
+**/=0D
+VOID=0D
+DumpVtdCapRegs (=0D
+ IN VTD_CAP_REG *CapReg=0D
+ )=0D
+{=0D
+ DEBUG((DEBUG_INFO, " CapReg - 0x%x\n", CapReg->Uint64));=0D
+ DEBUG((DEBUG_INFO, " ND - 0x%x\n", CapReg->Bits.ND));=0D
+ DEBUG((DEBUG_INFO, " AFL - 0x%x\n", CapReg->Bits.AFL));=0D
+ DEBUG((DEBUG_INFO, " RWBF - 0x%x\n", CapReg->Bits.RWBF));=0D
+ DEBUG((DEBUG_INFO, " PLMR - 0x%x\n", CapReg->Bits.PLMR));=0D
+ DEBUG((DEBUG_INFO, " PHMR - 0x%x\n", CapReg->Bits.PHMR));=0D
+ DEBUG((DEBUG_INFO, " CM - 0x%x\n", CapReg->Bits.CM));=0D
+ DEBUG((DEBUG_INFO, " SAGAW - 0x%x\n", CapReg->Bits.SAGAW));=0D
+ DEBUG((DEBUG_INFO, " MGAW - 0x%x\n", CapReg->Bits.MGAW));=0D
+ DEBUG((DEBUG_INFO, " ZLR - 0x%x\n", CapReg->Bits.ZLR));=0D
+ DEBUG((DEBUG_INFO, " FRO - 0x%x\n", CapReg->Bits.FRO));=0D
+ DEBUG((DEBUG_INFO, " SLLPS - 0x%x\n", CapReg->Bits.SLLPS));=0D
+ DEBUG((DEBUG_INFO, " PSI - 0x%x\n", CapReg->Bits.PSI));=0D
+ DEBUG((DEBUG_INFO, " NFR - 0x%x\n", CapReg->Bits.NFR));=0D
+ DEBUG((DEBUG_INFO, " MAMV - 0x%x\n", CapReg-&