/** @file\r
\r
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials are licensed and made available under\r
the terms and conditions of the BSD License which accompanies this distribution.\r
#include <Library/HobLib.h>\r
#include <IndustryStandard/Vtd.h>\r
#include <Ppi/IoMmu.h>\r
-#include <Ppi/VTdInfo.h>\r
+#include <Ppi/VtdInfo.h>\r
+#include <Ppi/MemoryDiscovered.h>\r
+#include <Ppi/EndOfPeiPhase.h>\r
\r
#include "IntelVTdPmrPei.h"\r
\r
#define TOTAL_DMA_BUFFER_SIZE SIZE_4MB\r
+#define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB\r
\r
-EDKII_VTD_INFO_PPI *mVTdInfoPpi;\r
-UINTN mDmaBufferBase;\r
-UINTN mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
-UINTN mDmaBufferCurrentTop;\r
-UINTN mDmaBufferCurrentBottom;\r
+EFI_GUID mVTdInfoGuid = {\r
+ 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }\r
+};\r
+\r
+EFI_GUID mDmaBufferInfoGuid = {\r
+ 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }\r
+};\r
+\r
+typedef struct {\r
+ UINTN DmaBufferBase;\r
+ UINTN DmaBufferSize;\r
+ UINTN DmaBufferCurrentTop;\r
+ UINTN DmaBufferCurrentBottom;\r
+} DMA_BUFFER_INFO;\r
\r
#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')\r
typedef struct {\r
\r
PEI Memory Layout:\r
\r
+ +------------------+ <=============== PHMR.Limit (+ alignment) (1 << (HostAddressWidth + 1))\r
+ | Mem Resource |\r
+ | |\r
+\r
+------------------+ <------- EfiMemoryTop\r
| PEI allocated |\r
- =========== +==================+\r
+ =========== +==================+ <=============== PHMR.Base\r
^ | Commom Buf |\r
| | -------------- |\r
DMA Buffer | * DMA FREE * |\r
| | -------------- |\r
V | Read/Write Buf |\r
- =========== +==================+\r
+ =========== +==================+ <=============== PLMR.Limit (+ alignment)\r
| PEI allocated |\r
| -------------- | <------- EfiFreeMemoryTop\r
| * PEI FREE * |\r
| Mem Alloc Hob |\r
+------------------+\r
\r
+ | |\r
+ | Mem Resource |\r
+ +------------------+ <=============== PLMR.Base (0)\r
**/\r
\r
-\r
/**\r
Set IOMMU attribute for a system memory.\r
\r
OUT VOID **Mapping\r
)\r
{\r
- MAP_INFO *MapInfo;\r
- UINTN Length;\r
+ MAP_INFO *MapInfo;\r
+ UINTN Length;\r
+ VOID *Hob;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+\r
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
\r
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||\r
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {\r
}\r
\r
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
\r
Length = *NumberOfBytes + sizeof(MAP_INFO);\r
- if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {\r
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));\r
ASSERT (FALSE);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- *DeviceAddress = mDmaBufferCurrentBottom;\r
- mDmaBufferCurrentBottom += Length;\r
+ *DeviceAddress = DmaBufferInfo->DmaBufferCurrentBottom;\r
+ DmaBufferInfo->DmaBufferCurrentBottom += Length;\r
\r
MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);\r
MapInfo->Signature = MAP_INFO_SIGNATURE;\r
IN VOID *Mapping\r
)\r
{\r
- MAP_INFO *MapInfo;\r
- UINTN Length;\r
+ MAP_INFO *MapInfo;\r
+ UINTN Length;\r
+ VOID *Hob;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+\r
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
\r
if (Mapping == NULL) {\r
return EFI_SUCCESS;\r
}\r
\r
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
\r
MapInfo = Mapping;\r
ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);\r
}\r
\r
Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);\r
- if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {\r
- mDmaBufferCurrentBottom -= Length;\r
+ if (DmaBufferInfo->DmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {\r
+ DmaBufferInfo->DmaBufferCurrentBottom -= Length;\r
}\r
\r
return EFI_SUCCESS;\r
\r
@retval EFI_SUCCESS The requested memory pages were allocated.\r
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are\r
- MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.\r
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.\r
\r
IN UINT64 Attributes\r
)\r
{\r
- UINTN Length;\r
+ UINTN Length;\r
+ VOID *Hob;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+\r
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
\r
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
\r
Length = EFI_PAGES_TO_SIZE(Pages);\r
- if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {\r
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));\r
ASSERT (FALSE);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);\r
- mDmaBufferCurrentTop -= Length;\r
+ *HostAddress = (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Length);\r
+ DmaBufferInfo->DmaBufferCurrentTop -= Length;\r
\r
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));\r
return EFI_SUCCESS;\r
IN VOID *HostAddress\r
)\r
{\r
- UINTN Length;\r
+ UINTN Length;\r
+ VOID *Hob;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+\r
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
\r
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
\r
Length = EFI_PAGES_TO_SIZE(Pages);\r
- if ((UINTN)HostAddress == mDmaBufferCurrentTop) {\r
- mDmaBufferCurrentTop += Length;\r
+ if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {\r
+ DmaBufferInfo->DmaBufferCurrentTop += Length;\r
}\r
\r
return EFI_SUCCESS;\r
(VOID *) &mIoMmuPpi\r
};\r
\r
-#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \\r
- EFI_RESOURCE_ATTRIBUTE_TESTED | \\r
- EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \\r
- EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \\r
- EFI_RESOURCE_ATTRIBUTE_64_BIT_IO \\r
- )\r
+/**\r
+ Initialize DMA protection.\r
+\r
+ @param VTdInfo The VTd engine context information.\r
+ @param DmaBufferSize the DMA buffer size\r
+ @param DmaBufferBase the DMA buffer base\r
+\r
+ @retval EFI_SUCCESS the DMA protection is initialized.\r
+ @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.\r
+**/\r
+EFI_STATUS\r
+InitDmaProtection (\r
+ IN VTD_INFO *VTdInfo,\r
+ IN UINTN DmaBufferSize,\r
+ OUT UINTN *DmaBufferBase\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT32 LowMemoryAlignment;\r
+ UINT64 HighMemoryAlignment;\r
+ UINTN MemoryAlignment;\r
+ UINTN LowBottom;\r
+ UINTN LowTop;\r
+ UINTN HighBottom;\r
+ UINT64 HighTop;\r
\r
-#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)\r
+ LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\r
+ HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\r
+ if (LowMemoryAlignment < HighMemoryAlignment) {\r
+ MemoryAlignment = (UINTN)HighMemoryAlignment;\r
+ } else {\r
+ MemoryAlignment = LowMemoryAlignment;\r
+ }\r
+ ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));\r
+ *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);\r
+ ASSERT (*DmaBufferBase != 0);\r
+ if (*DmaBufferBase == 0) {\r
+ DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
-#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)\r
+ LowBottom = 0;\r
+ LowTop = *DmaBufferBase;\r
+ HighBottom = *DmaBufferBase + DmaBufferSize;\r
+ HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);\r
\r
-#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)\r
+ Status = SetDmaProtectedRange (\r
+ VTdInfo,\r
+ VTdInfo->EngineMask,\r
+ (UINT32)LowBottom,\r
+ (UINT32)(LowTop - LowBottom),\r
+ HighBottom,\r
+ HighTop - HighBottom\r
+ );\r
\r
-GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mResourceTypeShortName[] = {\r
- "Mem",\r
- "MMIO",\r
- "I/O",\r
- "FD",\r
- "MM Port I/O",\r
- "Reserved Mem",\r
- "Reserved I/O",\r
-};\r
+ if (EFI_ERROR(Status)) {\r
+ FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));\r
+ }\r
+\r
+ return Status;\r
+}\r
\r
/**\r
- Return the short name of resource type.\r
+ Initializes the Intel VTd Info.\r
\r
- @param Type resource type.\r
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.\r
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.\r
\r
- @return the short name of resource type.\r
**/\r
-CHAR8 *\r
-ShortNameOfResourceType (\r
- IN UINT32 Type\r
+EFI_STATUS\r
+InitVTdInfo (\r
+ VOID\r
)\r
{\r
- if (Type < sizeof(mResourceTypeShortName) / sizeof(mResourceTypeShortName[0])) {\r
- return mResourceTypeShortName[Type];\r
- } else {\r
- return "Unknown";\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;\r
+ VOID *Hob;\r
+\r
+ Status = PeiServicesLocatePpi (\r
+ &gEdkiiVTdInfoPpiGuid,\r
+ 0,\r
+ NULL,\r
+ (VOID **)&AcpiDmarTable\r
+ );\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ DumpAcpiDMAR (AcpiDmarTable);\r
+\r
+ //\r
+ // Clear old VTdInfo Hob.\r
+ //\r
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+ if (Hob != NULL) {\r
+ ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID));\r
}\r
+\r
+ //\r
+ // Get DMAR information to local VTdInfo\r
+ //\r
+ Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.\r
+ //\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- Dump resource hob.\r
+ Initializes the Intel VTd PMR for all memory.\r
+\r
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.\r
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.\r
\r
- @param HobList the HOB list.\r
**/\r
-VOID\r
-DumpResourceHob (\r
- IN VOID *HobList\r
+EFI_STATUS\r
+InitVTdPmrForAll (\r
+ VOID\r
)\r
{\r
- EFI_PEI_HOB_POINTERS Hob;\r
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
-\r
- DEBUG ((DEBUG_VERBOSE, "Resource Descriptor HOBs\n"));\r
- for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
- ResourceHob = Hob.ResourceDescriptor;\r
- DEBUG ((DEBUG_VERBOSE,\r
- " BA=%016lx L=%016lx Attr=%08x ",\r
- ResourceHob->PhysicalStart,\r
- ResourceHob->ResourceLength,\r
- ResourceHob->ResourceAttribute\r
- ));\r
- DEBUG ((DEBUG_VERBOSE, ShortNameOfResourceType(ResourceHob->ResourceType)));\r
- switch (ResourceHob->ResourceType) {\r
- case EFI_RESOURCE_SYSTEM_MEMORY:\r
- if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) != 0) {\r
- DEBUG ((DEBUG_VERBOSE, " (Persistent)"));\r
- } else if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) != 0) {\r
- DEBUG ((DEBUG_VERBOSE, " (MoreReliable)"));\r
- } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {\r
- DEBUG ((DEBUG_VERBOSE, " (Tested)"));\r
- } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {\r
- DEBUG ((DEBUG_VERBOSE, " (Init)"));\r
- } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {\r
- DEBUG ((DEBUG_VERBOSE, " (Present)"));\r
- } else {\r
- DEBUG ((DEBUG_VERBOSE, " (Unknown)"));\r
- }\r
- break;\r
- default:\r
- break;\r
- }\r
- DEBUG ((DEBUG_VERBOSE, "\n"));\r
- }\r
- }\r
+ EFI_STATUS Status;\r
+ VOID *Hob;\r
+ VTD_INFO *VTdInfo;\r
+ UINTN LowBottom;\r
+ UINTN LowTop;\r
+ UINTN HighBottom;\r
+ UINT64 HighTop;\r
+\r
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+ VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+ LowBottom = 0;\r
+ LowTop = 0;\r
+ HighBottom = 0;\r
+ HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);\r
+\r
+ Status = SetDmaProtectedRange (\r
+ VTdInfo,\r
+ VTdInfo->EngineMask,\r
+ (UINT32)LowBottom,\r
+ (UINT32)(LowTop - LowBottom),\r
+ HighBottom,\r
+ HighTop - HighBottom\r
+ );\r
+\r
+ return Status;\r
}\r
\r
/**\r
- Dump PHIT hob.\r
+ Initializes the Intel VTd PMR for DMA buffer.\r
+\r
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.\r
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.\r
\r
- @param HobList the HOB list.\r
**/\r
-VOID\r
-DumpPhitHob (\r
- IN VOID *HobList\r
+EFI_STATUS\r
+InitVTdPmrForDma (\r
+ VOID\r
)\r
{\r
- EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
-\r
- PhitHob = HobList;\r
- ASSERT(GET_HOB_TYPE(HobList) == EFI_HOB_TYPE_HANDOFF);\r
- DEBUG ((DEBUG_VERBOSE, "PHIT HOB\n"));\r
- DEBUG ((DEBUG_VERBOSE, " PhitHob - 0x%x\n", PhitHob));\r
- DEBUG ((DEBUG_VERBOSE, " BootMode - 0x%x\n", PhitHob->BootMode));\r
- DEBUG ((DEBUG_VERBOSE, " EfiMemoryTop - 0x%016lx\n", PhitHob->EfiMemoryTop));\r
- DEBUG ((DEBUG_VERBOSE, " EfiMemoryBottom - 0x%016lx\n", PhitHob->EfiMemoryBottom));\r
- DEBUG ((DEBUG_VERBOSE, " EfiFreeMemoryTop - 0x%016lx\n", PhitHob->EfiFreeMemoryTop));\r
- DEBUG ((DEBUG_VERBOSE, " EfiFreeMemoryBottom - 0x%016lx\n", PhitHob->EfiFreeMemoryBottom));\r
- DEBUG ((DEBUG_VERBOSE, " EfiEndOfHobList - 0x%lx\n", PhitHob->EfiEndOfHobList));\r
+ EFI_STATUS Status;\r
+ VOID *Hob;\r
+ VTD_INFO *VTdInfo;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+\r
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+ VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+ //\r
+ // If there is RMRR memory, parse it here.\r
+ //\r
+ ParseDmarAcpiTableRmrr (VTdInfo);\r
+\r
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+ DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));\r
+ //\r
+ // Find a pre-memory in resource hob as DMA buffer\r
+ // Mark PEI memory to be DMA protected.\r
+ //\r
+ Status = InitDmaProtection (VTdInfo, DmaBufferInfo->DmaBufferSize, &DmaBufferInfo->DmaBufferBase);\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));\r
+\r
+ DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;\r
+ DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;\r
+\r
+ //\r
+ // Install PPI.\r
+ //\r
+ Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
+ ASSERT_EFI_ERROR(Status);\r
+\r
+ return Status;\r
}\r
\r
/**\r
- Get the highest memory.\r
+ This function handles S3 resume task at the end of PEI\r
\r
- @param HobList the HOB list.\r
+ @param[in] PeiServices Pointer to PEI Services Table.\r
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that\r
+ caused this function to execute.\r
+ @param[in] Ppi Pointer to the PPI data associated with this function.\r
\r
- @return the highest memory.\r
+ @retval EFI_STATUS Always return EFI_SUCCESS\r
**/\r
-UINT64\r
-GetTopMemory (\r
- IN VOID *HobList\r
+EFI_STATUS\r
+EFIAPI\r
+S3EndOfPeiNotify(\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
+ IN VOID *Ppi\r
)\r
{\r
- EFI_PEI_HOB_POINTERS Hob;\r
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
- UINT64 TopMemory;\r
- UINT64 ResourceTop;\r
-\r
- TopMemory = 0;\r
- for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
- if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
- ResourceHob = Hob.ResourceDescriptor;\r
- switch (ResourceHob->ResourceType) {\r
- case EFI_RESOURCE_SYSTEM_MEMORY:\r
- ResourceTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;\r
- if (TopMemory < ResourceTop) {\r
- TopMemory = ResourceTop;\r
- }\r
- break;\r
- default:\r
- break;\r
- }\r
- DEBUG ((DEBUG_VERBOSE, "\n"));\r
+ VOID *Hob;\r
+ VTD_INFO *VTdInfo;\r
+ UINT64 EngineMask;\r
+\r
+ DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));\r
+\r
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {\r
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+ if (Hob == NULL) {\r
+ return EFI_SUCCESS;\r
}\r
+ VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+ EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;\r
+ DisableDmaProtection (VTdInfo, EngineMask);\r
}\r
- return TopMemory;\r
+ return EFI_SUCCESS;\r
}\r
\r
+EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {\r
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEfiEndOfPeiSignalPpiGuid,\r
+ S3EndOfPeiNotify\r
+};\r
+\r
/**\r
- Initialize DMA protection.\r
+ This function handles VTd engine setup\r
\r
- @param DmaBufferSize the DMA buffer size\r
- @param DmaBufferBase the DMA buffer base\r
+ @param[in] PeiServices Pointer to PEI Services Table.\r
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that\r
+ caused this function to execute.\r
+ @param[in] Ppi Pointer to the PPI data associated with this function.\r
\r
- @retval EFI_SUCCESS the DMA protection is initialized.\r
- @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.\r
+ @retval EFI_STATUS Always return EFI_SUCCESS\r
**/\r
EFI_STATUS\r
-InitDmaProtection (\r
- IN UINTN DmaBufferSize,\r
- OUT UINTN *DmaBufferBase\r
+EFIAPI\r
+VTdInfoNotify (\r
+ IN EFI_PEI_SERVICES **PeiServices,\r
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
+ IN VOID *Ppi\r
)\r
{\r
EFI_STATUS Status;\r
- VOID *HobList;\r
- EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;\r
- UINT32 LowMemoryAlignment;\r
- UINT64 HighMemoryAlignment;\r
- UINTN MemoryAlignment;\r
- UINTN LowBottom;\r
- UINTN LowTop;\r
- UINTN HighBottom;\r
- UINT64 HighTop;\r
-\r
- HobList = GetHobList ();\r
- DumpPhitHob (HobList);\r
- DumpResourceHob (HobList);\r
+ VOID *MemoryDiscovered;\r
+ UINT64 EnabledEngineMask;\r
+ VOID *Hob;\r
+ VTD_INFO *VTdInfo;\r
+ BOOLEAN MemoryInitialized;\r
\r
- PhitHob = HobList;\r
+ DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));\r
\r
- ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);\r
-\r
- LowMemoryAlignment = GetLowMemoryAlignment ();\r
- HighMemoryAlignment = GetHighMemoryAlignment ();\r
- if (LowMemoryAlignment < HighMemoryAlignment) {\r
- MemoryAlignment = (UINTN)HighMemoryAlignment;\r
- } else {\r
- MemoryAlignment = LowMemoryAlignment;\r
- }\r
- ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));\r
- *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);\r
- if (*DmaBufferBase == 0) {\r
- DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));\r
- return EFI_OUT_OF_RESOURCES;\r
+ //\r
+ // Check if memory is initialized.\r
+ //\r
+ MemoryInitialized = FALSE;\r
+ Status = PeiServicesLocatePpi (\r
+ &gEfiPeiMemoryDiscoveredPpiGuid,\r
+ 0,\r
+ NULL,\r
+ &MemoryDiscovered\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ MemoryInitialized = TRUE;\r
}\r
\r
- LowBottom = 0;\r
- LowTop = *DmaBufferBase;\r
- HighBottom = *DmaBufferBase + DmaBufferSize;\r
- HighTop = GetTopMemory (HobList);\r
+ DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));\r
\r
- Status = SetDmaProtectedRange (\r
- (UINT32)LowBottom,\r
- (UINT32)(LowTop - LowBottom),\r
- HighBottom,\r
- HighTop - HighBottom\r
- );\r
+ if (!MemoryInitialized) {\r
+ //\r
+ // If the memory is not initialized,\r
+ // Protect all system memory\r
+ //\r
+ InitVTdInfo ();\r
+ InitVTdPmrForAll ();\r
+ } else {\r
+ //\r
+ // If the memory is initialized,\r
+ // Allocate DMA buffer and protect rest system memory\r
+ //\r
+\r
+ //\r
+ // NOTE: We need reinit VTdInfo because previous information might be overriden.\r
+ //\r
+ InitVTdInfo ();\r
+\r
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+ VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+ //\r
+ // NOTE: We need check if PMR is enabled or not.\r
+ //\r
+ EnabledEngineMask = GetDmaProtectionEnabledEngineMask (VTdInfo, VTdInfo->EngineMask);\r
+ if (EnabledEngineMask != 0) {\r
+ EnableVTdTranslationProtection (VTdInfo, EnabledEngineMask);\r
+ DisableDmaProtection (VTdInfo, EnabledEngineMask);\r
+ }\r
+ InitVTdPmrForDma ();\r
+ if (EnabledEngineMask != 0) {\r
+ DisableVTdTranslationProtection (VTdInfo, EnabledEngineMask);\r
+ }\r
\r
- if (EFI_ERROR(Status)) {\r
- FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));\r
}\r
\r
- return Status;\r
+ return EFI_SUCCESS;\r
}\r
\r
+EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc = {\r
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+ &gEdkiiVTdInfoPpiGuid,\r
+ VTdInfoNotify\r
+};\r
+\r
/**\r
Initializes the Intel VTd PMR PEIM.\r
\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_BOOT_MODE BootMode;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+\r
+ DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n"));\r
\r
if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
- Status = PeiServicesLocatePpi (\r
- &gEdkiiVTdInfoPpiGuid,\r
- 0,\r
- NULL,\r
- (VOID **)&mVTdInfoPpi\r
- );\r
- ASSERT_EFI_ERROR(Status);\r
-\r
- //\r
- // Find a pre-memory in resource hob as DMA buffer\r
- // Mark PEI memory to be DMA protected.\r
- //\r
- Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
+ DmaBufferInfo = BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_INFO));\r
+ ASSERT(DmaBufferInfo != NULL);\r
+ if (DmaBufferInfo == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
+ ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO));\r
\r
- DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));\r
- DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));\r
+ PeiServicesGetBootMode (&BootMode);\r
+\r
+ if (BootMode == BOOT_ON_S3_RESUME) {\r
+ DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;\r
+ } else {\r
+ DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
+ }\r
\r
- mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;\r
- mDmaBufferCurrentBottom = mDmaBufferBase;\r
+ Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);\r
+ ASSERT_EFI_ERROR (Status);\r
\r
//\r
- // Install PPI.\r
+ // Register EndOfPei Notify for S3\r
//\r
- Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
- ASSERT_EFI_ERROR(Status);\r
+ if (BootMode == BOOT_ON_S3_RESUME) {\r
+ Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
\r
- return Status;\r
+ return EFI_SUCCESS;\r
}\r
\r