3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License which accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/BaseLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/PeiServicesLib.h>
23 #include <Library/HobLib.h>
24 #include <IndustryStandard/Vtd.h>
25 #include <Ppi/IoMmu.h>
26 #include <Ppi/VtdInfo.h>
27 #include <Ppi/MemoryDiscovered.h>
28 #include <Ppi/EndOfPeiPhase.h>
30 #include "IntelVTdPmrPei.h"
32 #define TOTAL_DMA_BUFFER_SIZE SIZE_4MB
33 #define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB
35 EFI_GUID mVTdInfoGuid
= {
36 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }
39 EFI_GUID mDmaBufferInfoGuid
= {
40 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }
46 UINTN DmaBufferCurrentTop
;
47 UINTN DmaBufferCurrentBottom
;
50 #define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
53 EDKII_IOMMU_OPERATION Operation
;
55 EFI_PHYSICAL_ADDRESS HostAddress
;
56 EFI_PHYSICAL_ADDRESS DeviceAddress
;
63 +------------------+ <=============== PHMR.Limit (Top of memory)
67 +------------------+ <------- EfiMemoryTop
69 =========== +==================+ <=============== PHMR.Base
72 DMA Buffer | * DMA FREE * |
75 =========== +==================+ <=============== PLMR.Limit
77 | -------------- | <------- EfiFreeMemoryTop
79 | -------------- | <------- EfiFreeMemoryBottom
83 +------------------+ <------- EfiMemoryBottom / Stack Bottom
91 +------------------+ <=============== PLMR.Base (0)
95 Set IOMMU attribute for a system memory.
97 If the IOMMU PPI exists, the system memory cannot be used
100 When a device requests a DMA access for a system memory,
101 the device driver need use SetAttribute() to update the IOMMU
102 attribute to request DMA access (read and/or write).
104 @param[in] This The PPI instance pointer.
105 @param[in] Mapping The mapping value returned from Map().
106 @param[in] IoMmuAccess The IOMMU access.
108 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
109 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
110 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
111 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
112 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping.
113 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
114 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
119 PeiIoMmuSetAttribute (
120 IN EDKII_IOMMU_PPI
*This
,
122 IN UINT64 IoMmuAccess
129 Provides the controller-specific addresses required to access system memory from a
132 @param This The PPI instance pointer.
133 @param Operation Indicates if the bus master is going to read or write to system memory.
134 @param HostAddress The system memory address to map to the PCI controller.
135 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
137 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
138 access the hosts HostAddress.
139 @param Mapping A resulting value to pass to Unmap().
141 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
142 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
143 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
144 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
145 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
151 IN EDKII_IOMMU_PPI
*This
,
152 IN EDKII_IOMMU_OPERATION Operation
,
153 IN VOID
*HostAddress
,
154 IN OUT UINTN
*NumberOfBytes
,
155 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
162 DMA_BUFFER_INFO
*DmaBufferInfo
;
164 Hob
= GetFirstGuidHob (&mDmaBufferInfoGuid
);
165 DmaBufferInfo
= GET_GUID_HOB_DATA(Hob
);
167 if (Operation
== EdkiiIoMmuOperationBusMasterCommonBuffer
||
168 Operation
== EdkiiIoMmuOperationBusMasterCommonBuffer64
) {
169 *DeviceAddress
= (UINTN
)HostAddress
;
174 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress
, *NumberOfBytes
));
175 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentTop - %x\n", DmaBufferInfo
->DmaBufferCurrentTop
));
176 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo
->DmaBufferCurrentBottom
));
178 Length
= *NumberOfBytes
+ sizeof(MAP_INFO
);
179 if (Length
> DmaBufferInfo
->DmaBufferCurrentTop
- DmaBufferInfo
->DmaBufferCurrentBottom
) {
180 DEBUG ((DEBUG_ERROR
, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
182 return EFI_OUT_OF_RESOURCES
;
185 *DeviceAddress
= DmaBufferInfo
->DmaBufferCurrentBottom
;
186 DmaBufferInfo
->DmaBufferCurrentBottom
+= Length
;
188 MapInfo
= (VOID
*)(UINTN
)(*DeviceAddress
+ *NumberOfBytes
);
189 MapInfo
->Signature
= MAP_INFO_SIGNATURE
;
190 MapInfo
->Operation
= Operation
;
191 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
192 MapInfo
->HostAddress
= (UINTN
)HostAddress
;
193 MapInfo
->DeviceAddress
= *DeviceAddress
;
195 DEBUG ((DEBUG_VERBOSE
, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation
, (UINTN
)*DeviceAddress
, MapInfo
));
198 // If this is a read operation from the Bus Master's point of view,
199 // then copy the contents of the real buffer into the mapped buffer
200 // so the Bus Master can read the contents of the real buffer.
202 if (Operation
== EdkiiIoMmuOperationBusMasterRead
||
203 Operation
== EdkiiIoMmuOperationBusMasterRead64
) {
205 (VOID
*) (UINTN
) MapInfo
->DeviceAddress
,
206 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
207 MapInfo
->NumberOfBytes
215 Completes the Map() operation and releases any corresponding resources.
217 @param This The PPI instance pointer.
218 @param Mapping The mapping value returned from Map().
220 @retval EFI_SUCCESS The range was unmapped.
221 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
222 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
227 IN EDKII_IOMMU_PPI
*This
,
234 DMA_BUFFER_INFO
*DmaBufferInfo
;
236 Hob
= GetFirstGuidHob (&mDmaBufferInfoGuid
);
237 DmaBufferInfo
= GET_GUID_HOB_DATA(Hob
);
239 if (Mapping
== NULL
) {
243 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuUnmap - Mapping - %x\n", Mapping
));
244 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentTop - %x\n", DmaBufferInfo
->DmaBufferCurrentTop
));
245 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo
->DmaBufferCurrentBottom
));
248 ASSERT (MapInfo
->Signature
== MAP_INFO_SIGNATURE
);
249 DEBUG ((DEBUG_VERBOSE
, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo
->Operation
, (UINTN
)MapInfo
->DeviceAddress
, MapInfo
->NumberOfBytes
));
252 // If this is a write operation from the Bus Master's point of view,
253 // then copy the contents of the mapped buffer into the real buffer
254 // so the processor can read the contents of the real buffer.
256 if (MapInfo
->Operation
== EdkiiIoMmuOperationBusMasterWrite
||
257 MapInfo
->Operation
== EdkiiIoMmuOperationBusMasterWrite64
) {
259 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
260 (VOID
*) (UINTN
) MapInfo
->DeviceAddress
,
261 MapInfo
->NumberOfBytes
265 Length
= MapInfo
->NumberOfBytes
+ sizeof(MAP_INFO
);
266 if (DmaBufferInfo
->DmaBufferCurrentBottom
== MapInfo
->DeviceAddress
+ Length
) {
267 DmaBufferInfo
->DmaBufferCurrentBottom
-= Length
;
274 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
275 OperationBusMasterCommonBuffer64 mapping.
277 @param This The PPI instance pointer.
278 @param MemoryType The type of memory to allocate, EfiBootServicesData or
279 EfiRuntimeServicesData.
280 @param Pages The number of pages to allocate.
281 @param HostAddress A pointer to store the base system memory address of the
283 @param Attributes The requested bit mask of attributes for the allocated range.
285 @retval EFI_SUCCESS The requested memory pages were allocated.
286 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
287 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
288 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
289 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
294 PeiIoMmuAllocateBuffer (
295 IN EDKII_IOMMU_PPI
*This
,
296 IN EFI_MEMORY_TYPE MemoryType
,
298 IN OUT VOID
**HostAddress
,
304 DMA_BUFFER_INFO
*DmaBufferInfo
;
306 Hob
= GetFirstGuidHob (&mDmaBufferInfoGuid
);
307 DmaBufferInfo
= GET_GUID_HOB_DATA(Hob
);
309 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuAllocateBuffer - page - %x\n", Pages
));
310 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentTop - %x\n", DmaBufferInfo
->DmaBufferCurrentTop
));
311 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo
->DmaBufferCurrentBottom
));
313 Length
= EFI_PAGES_TO_SIZE(Pages
);
314 if (Length
> DmaBufferInfo
->DmaBufferCurrentTop
- DmaBufferInfo
->DmaBufferCurrentBottom
) {
315 DEBUG ((DEBUG_ERROR
, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
317 return EFI_OUT_OF_RESOURCES
;
319 *HostAddress
= (VOID
*)(UINTN
)(DmaBufferInfo
->DmaBufferCurrentTop
- Length
);
320 DmaBufferInfo
->DmaBufferCurrentTop
-= Length
;
322 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress
));
327 Frees memory that was allocated with AllocateBuffer().
329 @param This The PPI instance pointer.
330 @param Pages The number of pages to free.
331 @param HostAddress The base system memory address of the allocated range.
333 @retval EFI_SUCCESS The requested memory pages were freed.
334 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
335 was not allocated with AllocateBuffer().
341 IN EDKII_IOMMU_PPI
*This
,
348 DMA_BUFFER_INFO
*DmaBufferInfo
;
350 Hob
= GetFirstGuidHob (&mDmaBufferInfoGuid
);
351 DmaBufferInfo
= GET_GUID_HOB_DATA(Hob
);
353 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages
, HostAddress
));
354 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentTop - %x\n", DmaBufferInfo
->DmaBufferCurrentTop
));
355 DEBUG ((DEBUG_VERBOSE
, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo
->DmaBufferCurrentBottom
));
357 Length
= EFI_PAGES_TO_SIZE(Pages
);
358 if ((UINTN
)HostAddress
== DmaBufferInfo
->DmaBufferCurrentTop
) {
359 DmaBufferInfo
->DmaBufferCurrentTop
+= Length
;
365 EDKII_IOMMU_PPI mIoMmuPpi
= {
366 EDKII_IOMMU_PPI_REVISION
,
367 PeiIoMmuSetAttribute
,
370 PeiIoMmuAllocateBuffer
,
374 CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList
= {
375 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
380 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
381 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
382 EFI_RESOURCE_ATTRIBUTE_TESTED | \
383 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
384 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
385 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO \
388 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)
390 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)
392 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
394 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mResourceTypeShortName
[] = {
405 Return the short name of resource type.
407 @param Type resource type.
409 @return the short name of resource type.
412 ShortNameOfResourceType (
416 if (Type
< sizeof(mResourceTypeShortName
) / sizeof(mResourceTypeShortName
[0])) {
417 return mResourceTypeShortName
[Type
];
426 @param HobList the HOB list.
433 EFI_PEI_HOB_POINTERS Hob
;
434 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
436 DEBUG ((DEBUG_VERBOSE
, "Resource Descriptor HOBs\n"));
437 for (Hob
.Raw
= HobList
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
438 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
439 ResourceHob
= Hob
.ResourceDescriptor
;
440 DEBUG ((DEBUG_VERBOSE
,
441 " BA=%016lx L=%016lx Attr=%08x ",
442 ResourceHob
->PhysicalStart
,
443 ResourceHob
->ResourceLength
,
444 ResourceHob
->ResourceAttribute
446 DEBUG ((DEBUG_VERBOSE
, ShortNameOfResourceType(ResourceHob
->ResourceType
)));
447 switch (ResourceHob
->ResourceType
) {
448 case EFI_RESOURCE_SYSTEM_MEMORY
:
449 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) != 0) {
450 DEBUG ((DEBUG_VERBOSE
, " (Persistent)"));
451 } else if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) != 0) {
452 DEBUG ((DEBUG_VERBOSE
, " (MoreReliable)"));
453 } else if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
454 DEBUG ((DEBUG_VERBOSE
, " (Tested)"));
455 } else if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
456 DEBUG ((DEBUG_VERBOSE
, " (Init)"));
457 } else if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
458 DEBUG ((DEBUG_VERBOSE
, " (Present)"));
460 DEBUG ((DEBUG_VERBOSE
, " (Unknown)"));
466 DEBUG ((DEBUG_VERBOSE
, "\n"));
474 @param HobList the HOB list.
481 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
484 ASSERT(GET_HOB_TYPE(HobList
) == EFI_HOB_TYPE_HANDOFF
);
485 DEBUG ((DEBUG_VERBOSE
, "PHIT HOB\n"));
486 DEBUG ((DEBUG_VERBOSE
, " PhitHob - 0x%x\n", PhitHob
));
487 DEBUG ((DEBUG_VERBOSE
, " BootMode - 0x%x\n", PhitHob
->BootMode
));
488 DEBUG ((DEBUG_VERBOSE
, " EfiMemoryTop - 0x%016lx\n", PhitHob
->EfiMemoryTop
));
489 DEBUG ((DEBUG_VERBOSE
, " EfiMemoryBottom - 0x%016lx\n", PhitHob
->EfiMemoryBottom
));
490 DEBUG ((DEBUG_VERBOSE
, " EfiFreeMemoryTop - 0x%016lx\n", PhitHob
->EfiFreeMemoryTop
));
491 DEBUG ((DEBUG_VERBOSE
, " EfiFreeMemoryBottom - 0x%016lx\n", PhitHob
->EfiFreeMemoryBottom
));
492 DEBUG ((DEBUG_VERBOSE
, " EfiEndOfHobList - 0x%lx\n", PhitHob
->EfiEndOfHobList
));
496 Get the highest memory.
498 @return the highest memory.
506 EFI_PEI_HOB_POINTERS Hob
;
507 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
511 HobList
= GetHobList ();
514 for (Hob
.Raw
= HobList
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
515 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
516 ResourceHob
= Hob
.ResourceDescriptor
;
517 switch (ResourceHob
->ResourceType
) {
518 case EFI_RESOURCE_SYSTEM_MEMORY
:
519 ResourceTop
= ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
;
520 if (TopMemory
< ResourceTop
) {
521 TopMemory
= ResourceTop
;
527 DEBUG ((DEBUG_VERBOSE
, "\n"));
534 Initialize DMA protection.
536 @param VTdInfo The VTd engine context information.
537 @param DmaBufferSize the DMA buffer size
538 @param DmaBufferBase the DMA buffer base
540 @retval EFI_SUCCESS the DMA protection is initialized.
541 @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.
545 IN VTD_INFO
*VTdInfo
,
546 IN UINTN DmaBufferSize
,
547 OUT UINTN
*DmaBufferBase
552 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
553 UINT32 LowMemoryAlignment
;
554 UINT64 HighMemoryAlignment
;
555 UINTN MemoryAlignment
;
561 HobList
= GetHobList ();
562 DumpPhitHob (HobList
);
563 DumpResourceHob (HobList
);
567 ASSERT (PhitHob
->EfiMemoryBottom
< PhitHob
->EfiMemoryTop
);
569 LowMemoryAlignment
= GetLowMemoryAlignment (VTdInfo
, VTdInfo
->EngineMask
);
570 HighMemoryAlignment
= GetHighMemoryAlignment (VTdInfo
, VTdInfo
->EngineMask
);
571 if (LowMemoryAlignment
< HighMemoryAlignment
) {
572 MemoryAlignment
= (UINTN
)HighMemoryAlignment
;
574 MemoryAlignment
= LowMemoryAlignment
;
576 ASSERT (DmaBufferSize
== ALIGN_VALUE(DmaBufferSize
, MemoryAlignment
));
577 *DmaBufferBase
= (UINTN
)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize
), MemoryAlignment
);
578 ASSERT (*DmaBufferBase
!= 0);
579 if (*DmaBufferBase
== 0) {
580 DEBUG ((DEBUG_INFO
, " InitDmaProtection : OutOfResource\n"));
581 return EFI_OUT_OF_RESOURCES
;
585 LowTop
= *DmaBufferBase
;
586 HighBottom
= *DmaBufferBase
+ DmaBufferSize
;
587 HighTop
= GetTopMemory ();
589 Status
= SetDmaProtectedRange (
593 (UINT32
)(LowTop
- LowBottom
),
598 if (EFI_ERROR(Status
)) {
599 FreePages ((VOID
*)*DmaBufferBase
, EFI_SIZE_TO_PAGES(DmaBufferSize
));
606 Initializes the Intel VTd Info.
608 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
609 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
618 EFI_ACPI_DMAR_HEADER
*AcpiDmarTable
;
621 Status
= PeiServicesLocatePpi (
622 &gEdkiiVTdInfoPpiGuid
,
625 (VOID
**)&AcpiDmarTable
627 ASSERT_EFI_ERROR(Status
);
629 DumpAcpiDMAR (AcpiDmarTable
);
632 // Clear old VTdInfo Hob.
634 Hob
= GetFirstGuidHob (&mVTdInfoGuid
);
636 ZeroMem (&((EFI_HOB_GUID_TYPE
*)Hob
)->Name
, sizeof(EFI_GUID
));
640 // Get DMAR information to local VTdInfo
642 Status
= ParseDmarAcpiTableDrhd (AcpiDmarTable
);
643 if (EFI_ERROR(Status
)) {
648 // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.
655 Initializes the Intel VTd PMR for all memory.
657 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
658 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
674 Hob
= GetFirstGuidHob (&mVTdInfoGuid
);
675 VTdInfo
= GET_GUID_HOB_DATA(Hob
);
680 HighTop
= LShiftU64 (1, VTdInfo
->HostAddressWidth
);
682 Status
= SetDmaProtectedRange (
686 (UINT32
)(LowTop
- LowBottom
),
695 Initializes the Intel VTd PMR for DMA buffer.
697 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
698 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
709 DMA_BUFFER_INFO
*DmaBufferInfo
;
711 Hob
= GetFirstGuidHob (&mVTdInfoGuid
);
712 VTdInfo
= GET_GUID_HOB_DATA(Hob
);
715 // If there is RMRR memory, parse it here.
717 ParseDmarAcpiTableRmrr (VTdInfo
);
719 Hob
= GetFirstGuidHob (&mDmaBufferInfoGuid
);
720 DmaBufferInfo
= GET_GUID_HOB_DATA(Hob
);
722 DEBUG ((DEBUG_INFO
, " DmaBufferSize : 0x%x\n", DmaBufferInfo
->DmaBufferSize
));
724 // Find a pre-memory in resource hob as DMA buffer
725 // Mark PEI memory to be DMA protected.
727 Status
= InitDmaProtection (VTdInfo
, DmaBufferInfo
->DmaBufferSize
, &DmaBufferInfo
->DmaBufferBase
);
728 if (EFI_ERROR(Status
)) {
732 DEBUG ((DEBUG_INFO
, " DmaBufferBase : 0x%x\n", DmaBufferInfo
->DmaBufferBase
));
734 DmaBufferInfo
->DmaBufferCurrentTop
= DmaBufferInfo
->DmaBufferBase
+ DmaBufferInfo
->DmaBufferSize
;
735 DmaBufferInfo
->DmaBufferCurrentBottom
= DmaBufferInfo
->DmaBufferBase
;
740 Status
= PeiServicesInstallPpi (&mIoMmuPpiList
);
741 ASSERT_EFI_ERROR(Status
);
747 This function handles S3 resume task at the end of PEI
749 @param[in] PeiServices Pointer to PEI Services Table.
750 @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
751 caused this function to execute.
752 @param[in] Ppi Pointer to the PPI data associated with this function.
754 @retval EFI_STATUS Always return EFI_SUCCESS
759 IN EFI_PEI_SERVICES
**PeiServices
,
760 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDesc
,
768 DEBUG((DEBUG_INFO
, "VTdPmr S3EndOfPeiNotify\n"));
770 if ((PcdGet8(PcdVTdPolicyPropertyMask
) & BIT1
) == 0) {
771 Hob
= GetFirstGuidHob (&mVTdInfoGuid
);
775 VTdInfo
= GET_GUID_HOB_DATA(Hob
);
777 EngineMask
= LShiftU64 (1, VTdInfo
->VTdEngineCount
) - 1;
778 DisableDmaProtection (VTdInfo
, EngineMask
);
783 EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc
= {
784 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
785 &gEfiEndOfPeiSignalPpiGuid
,
790 This function handles VTd engine setup
792 @param[in] PeiServices Pointer to PEI Services Table.
793 @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
794 caused this function to execute.
795 @param[in] Ppi Pointer to the PPI data associated with this function.
797 @retval EFI_STATUS Always return EFI_SUCCESS
802 IN EFI_PEI_SERVICES
**PeiServices
,
803 IN EFI_PEI_NOTIFY_DESCRIPTOR
*NotifyDesc
,
808 VOID
*MemoryDiscovered
;
809 UINT64 EnabledEngineMask
;
812 BOOLEAN MemoryInitialized
;
814 DEBUG ((DEBUG_INFO
, "VTdInfoNotify\n"));
817 // Check if memory is initialized.
819 MemoryInitialized
= FALSE
;
820 Status
= PeiServicesLocatePpi (
821 &gEfiPeiMemoryDiscoveredPpiGuid
,
826 if (!EFI_ERROR(Status
)) {
827 MemoryInitialized
= TRUE
;
830 DEBUG ((DEBUG_INFO
, "MemoryInitialized - %x\n", MemoryInitialized
));
832 if (!MemoryInitialized
) {
834 // If the memory is not initialized,
835 // Protect all system memory
841 // If the memory is initialized,
842 // Allocate DMA buffer and protect rest system memory
846 // NOTE: We need reinit VTdInfo because previous information might be overriden.
850 Hob
= GetFirstGuidHob (&mVTdInfoGuid
);
851 VTdInfo
= GET_GUID_HOB_DATA(Hob
);
854 // NOTE: We need check if PMR is enabled or not.
856 EnabledEngineMask
= GetDmaProtectionEnabledEngineMask (VTdInfo
, VTdInfo
->EngineMask
);
857 if (EnabledEngineMask
!= 0) {
858 EnableVTdTranslationProtection (VTdInfo
, EnabledEngineMask
);
859 DisableDmaProtection (VTdInfo
, EnabledEngineMask
);
862 if (EnabledEngineMask
!= 0) {
863 DisableVTdTranslationProtection (VTdInfo
, EnabledEngineMask
);
871 EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc
= {
872 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
),
873 &gEdkiiVTdInfoPpiGuid
,
878 Initializes the Intel VTd PMR PEIM.
880 @param FileHandle Handle of the file being invoked.
881 @param PeiServices Describes the list of possible PEI Services.
883 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
884 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
889 IntelVTdPmrInitialize (
890 IN EFI_PEI_FILE_HANDLE FileHandle
,
891 IN CONST EFI_PEI_SERVICES
**PeiServices
895 EFI_BOOT_MODE BootMode
;
896 DMA_BUFFER_INFO
*DmaBufferInfo
;
898 DEBUG ((DEBUG_INFO
, "IntelVTdPmrInitialize\n"));
900 if ((PcdGet8(PcdVTdPolicyPropertyMask
) & BIT0
) == 0) {
901 return EFI_UNSUPPORTED
;
904 DmaBufferInfo
= BuildGuidHob (&mDmaBufferInfoGuid
, sizeof(DMA_BUFFER_INFO
));
905 ASSERT(DmaBufferInfo
!= NULL
);
906 if (DmaBufferInfo
== NULL
) {
907 return EFI_OUT_OF_RESOURCES
;
909 ZeroMem (DmaBufferInfo
, sizeof(DMA_BUFFER_INFO
));
911 PeiServicesGetBootMode (&BootMode
);
913 if (BootMode
== BOOT_ON_S3_RESUME
) {
914 DmaBufferInfo
->DmaBufferSize
= TOTAL_DMA_BUFFER_SIZE_S3
;
916 DmaBufferInfo
->DmaBufferSize
= TOTAL_DMA_BUFFER_SIZE
;
919 Status
= PeiServicesNotifyPpi (&mVTdInfoNotifyDesc
);
920 ASSERT_EFI_ERROR (Status
);
923 // Register EndOfPei Notify for S3
925 if (BootMode
== BOOT_ON_S3_RESUME
) {
926 Status
= PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc
);
927 ASSERT_EFI_ERROR (Status
);