\r
#include "IntelVTdPmrPei.h"\r
\r
-#define TOTAL_DMA_BUFFER_SIZE SIZE_4MB\r
-#define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB\r
-\r
EFI_GUID mVTdInfoGuid = {\r
0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }\r
};\r
\r
PEI Memory Layout:\r
\r
- +------------------+ <=============== PHMR.Limit (+ alignment) (Top of memory)\r
+ +------------------+ <=============== PHMR.Limit (+ alignment) (1 << (HostAddressWidth + 1))\r
| Mem Resource |\r
| |\r
\r
@retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping.\r
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.\r
@retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.\r
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are\r
+ not available to be allocated yet.\r
\r
**/\r
EFI_STATUS\r
IN UINT64 IoMmuAccess\r
)\r
{\r
+ VOID *Hob;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+\r
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+ if (DmaBufferInfo->DmaBufferCurrentTop == 0) {\r
+ return EFI_NOT_AVAILABLE_YET;\r
+ }\r
+\r
return EFI_SUCCESS;\r
}\r
\r
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
@retval EFI_DEVICE_ERROR The system hardware could not map the requested address.\r
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are\r
+ not available to be allocated yet.\r
\r
**/\r
EFI_STATUS\r
Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
\r
+ DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
+\r
+ if (DmaBufferInfo->DmaBufferCurrentTop == 0) {\r
+ return EFI_NOT_AVAILABLE_YET;\r
+ }\r
+\r
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||\r
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {\r
*DeviceAddress = (UINTN)HostAddress;\r
- *Mapping = 0;\r
+ *Mapping = NULL;\r
return EFI_SUCCESS;\r
}\r
\r
- DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));\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 > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));\r
@retval EFI_SUCCESS The range was unmapped.\r
@retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().\r
@retval EFI_DEVICE_ERROR The data was not committed to the target system memory.\r
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are\r
+ not available to be allocated yet.\r
+\r
**/\r
EFI_STATUS\r
EFIAPI\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, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
\r
+ if (DmaBufferInfo->DmaBufferCurrentTop == 0) {\r
+ return EFI_NOT_AVAILABLE_YET;\r
+ }\r
+\r
+ if (Mapping == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
MapInfo = Mapping;\r
ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);\r
DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo->Operation, (UINTN)MapInfo->DeviceAddress, MapInfo->NumberOfBytes));\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
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are\r
+ not available to be allocated yet.\r
\r
**/\r
EFI_STATUS\r
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
\r
+ if (DmaBufferInfo->DmaBufferCurrentTop == 0) {\r
+ return EFI_NOT_AVAILABLE_YET;\r
+ }\r
+\r
Length = EFI_PAGES_TO_SIZE(Pages);\r
if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));\r
@retval EFI_SUCCESS The requested memory pages were freed.\r
@retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages\r
was not allocated with AllocateBuffer().\r
+ @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are\r
+ not available to be allocated yet.\r
\r
**/\r
EFI_STATUS\r
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
\r
+ if (DmaBufferInfo->DmaBufferCurrentTop == 0) {\r
+ return EFI_NOT_AVAILABLE_YET;\r
+ }\r
+\r
Length = EFI_PAGES_TO_SIZE(Pages);\r
if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {\r
DmaBufferInfo->DmaBufferCurrentTop += Length;\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
-#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)\r
-\r
-#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)\r
-\r
-#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)\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
-\r
-/**\r
- Return the short name of resource type.\r
-\r
- @param Type resource type.\r
-\r
- @return the short name of resource type.\r
-**/\r
-CHAR8 *\r
-ShortNameOfResourceType (\r
- IN UINT32 Type\r
- )\r
-{\r
- if (Type < sizeof(mResourceTypeShortName) / sizeof(mResourceTypeShortName[0])) {\r
- return mResourceTypeShortName[Type];\r
- } else {\r
- return "Unknown";\r
- }\r
-}\r
-\r
-/**\r
- Dump resource hob.\r
-\r
- @param HobList the HOB list.\r
-**/\r
-VOID\r
-DumpResourceHob (\r
- IN VOID *HobList\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
-}\r
-\r
-/**\r
- Dump PHIT hob.\r
-\r
- @param HobList the HOB list.\r
-**/\r
-VOID\r
-DumpPhitHob (\r
- IN VOID *HobList\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
-}\r
-\r
-/**\r
- Get the highest memory.\r
-\r
- @return the highest memory.\r
-**/\r
-UINT64\r
-GetTopMemory (\r
- VOID\r
- )\r
-{\r
- VOID *HobList;\r
- EFI_PEI_HOB_POINTERS Hob;\r
- EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
- UINT64 TopMemory;\r
- UINT64 ResourceTop;\r
-\r
- HobList = GetHobList ();\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
- }\r
- }\r
- return TopMemory;\r
-}\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
+ IN VTD_INFO *VTdInfo\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 LowTop;\r
UINTN HighBottom;\r
UINT64 HighTop;\r
+ DMA_BUFFER_INFO *DmaBufferInfo;\r
+ VOID *Hob;\r
+ EFI_PEI_PPI_DESCRIPTOR *OldDescriptor;\r
+ EDKII_IOMMU_PPI *OldIoMmuPpi;\r
\r
- HobList = GetHobList ();\r
- DumpPhitHob (HobList);\r
- DumpResourceHob (HobList);\r
-\r
- PhitHob = HobList;\r
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
\r
- ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);\r
+ DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));\r
\r
LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\r
HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\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
+ ASSERT (DmaBufferInfo->DmaBufferSize == ALIGN_VALUE(DmaBufferInfo->DmaBufferSize, MemoryAlignment));\r
+ DmaBufferInfo->DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize), MemoryAlignment);\r
+ ASSERT (DmaBufferInfo->DmaBufferBase != 0);\r
+ if (DmaBufferInfo->DmaBufferBase == 0) {\r
DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));\r
return EFI_OUT_OF_RESOURCES;\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
+ // (Re)Install PPI.\r
+ //\r
+ Status = PeiServicesLocatePpi (\r
+ &gEdkiiIoMmuPpiGuid,\r
+ 0,\r
+ &OldDescriptor,\r
+ (VOID **) &OldIoMmuPpi\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = PeiServicesReInstallPpi (OldDescriptor, &mIoMmuPpiList);\r
+ } else {\r
+ Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
LowBottom = 0;\r
- LowTop = *DmaBufferBase;\r
- HighBottom = *DmaBufferBase + DmaBufferSize;\r
- HighTop = GetTopMemory ();\r
+ LowTop = DmaBufferInfo->DmaBufferBase;\r
+ HighBottom = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;\r
+ HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);\r
\r
Status = SetDmaProtectedRange (\r
VTdInfo,\r
);\r
\r
if (EFI_ERROR(Status)) {\r
- FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));\r
+ FreePages ((VOID *)DmaBufferInfo->DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferInfo->DmaBufferSize));\r
}\r
\r
return Status;\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
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
+ // Allocate a range in PEI memory as DMA buffer\r
+ // Mark others 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
+ Status = InitDmaProtection (VTdInfo);\r
\r
return Status;\r
}\r
//\r
InitVTdInfo ();\r
InitVTdPmrForAll ();\r
+\r
+ //\r
+ // Install PPI.\r
+ //\r
+ Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
+ ASSERT_EFI_ERROR(Status);\r
} else {\r
//\r
// If the memory is initialized,\r
PeiServicesGetBootMode (&BootMode);\r
\r
if (BootMode == BOOT_ON_S3_RESUME) {\r
- DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;\r
+ DmaBufferInfo->DmaBufferSize = PcdGet32 (PcdVTdPeiDmaBufferSizeS3);\r
} else {\r
- DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
+ DmaBufferInfo->DmaBufferSize = PcdGet32 (PcdVTdPeiDmaBufferSize);\r
}\r
\r
Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);\r