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>
28 #include "IntelVTdPmrPei.h"
30 #define TOTAL_DMA_BUFFER_SIZE SIZE_4MB
32 EFI_ACPI_DMAR_HEADER
*mAcpiDmarTable
;
36 UINTN mDmaBufferSize
= TOTAL_DMA_BUFFER_SIZE
;
37 UINTN mDmaBufferCurrentTop
;
38 UINTN mDmaBufferCurrentBottom
;
40 #define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
43 EDKII_IOMMU_OPERATION Operation
;
45 EFI_PHYSICAL_ADDRESS HostAddress
;
46 EFI_PHYSICAL_ADDRESS DeviceAddress
;
53 +------------------+ <=============== PHMR.Limit (Top of memory)
57 +------------------+ <------- EfiMemoryTop
59 =========== +==================+ <=============== PHMR.Base
62 DMA Buffer | * DMA FREE * |
65 =========== +==================+ <=============== PLMR.Limit
67 | -------------- | <------- EfiFreeMemoryTop
69 | -------------- | <------- EfiFreeMemoryBottom
73 +------------------+ <------- EfiMemoryBottom / Stack Bottom
81 +------------------+ <=============== PLMR.Base (0)
86 Set IOMMU attribute for a system memory.
88 If the IOMMU PPI exists, the system memory cannot be used
91 When a device requests a DMA access for a system memory,
92 the device driver need use SetAttribute() to update the IOMMU
93 attribute to request DMA access (read and/or write).
95 @param[in] This The PPI instance pointer.
96 @param[in] Mapping The mapping value returned from Map().
97 @param[in] IoMmuAccess The IOMMU access.
99 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
100 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
101 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
102 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
103 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping.
104 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
105 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
110 PeiIoMmuSetAttribute (
111 IN EDKII_IOMMU_PPI
*This
,
113 IN UINT64 IoMmuAccess
120 Provides the controller-specific addresses required to access system memory from a
123 @param This The PPI instance pointer.
124 @param Operation Indicates if the bus master is going to read or write to system memory.
125 @param HostAddress The system memory address to map to the PCI controller.
126 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
128 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
129 access the hosts HostAddress.
130 @param Mapping A resulting value to pass to Unmap().
132 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
133 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
134 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
135 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
136 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
142 IN EDKII_IOMMU_PPI
*This
,
143 IN EDKII_IOMMU_OPERATION Operation
,
144 IN VOID
*HostAddress
,
145 IN OUT UINTN
*NumberOfBytes
,
146 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
153 if (Operation
== EdkiiIoMmuOperationBusMasterCommonBuffer
||
154 Operation
== EdkiiIoMmuOperationBusMasterCommonBuffer64
) {
155 *DeviceAddress
= (UINTN
)HostAddress
;
160 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress
, *NumberOfBytes
));
161 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop
));
162 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom
));
164 Length
= *NumberOfBytes
+ sizeof(MAP_INFO
);
165 if (Length
> mDmaBufferCurrentTop
- mDmaBufferCurrentBottom
) {
166 DEBUG ((DEBUG_ERROR
, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
168 return EFI_OUT_OF_RESOURCES
;
171 *DeviceAddress
= mDmaBufferCurrentBottom
;
172 mDmaBufferCurrentBottom
+= Length
;
174 MapInfo
= (VOID
*)(UINTN
)(*DeviceAddress
+ *NumberOfBytes
);
175 MapInfo
->Signature
= MAP_INFO_SIGNATURE
;
176 MapInfo
->Operation
= Operation
;
177 MapInfo
->NumberOfBytes
= *NumberOfBytes
;
178 MapInfo
->HostAddress
= (UINTN
)HostAddress
;
179 MapInfo
->DeviceAddress
= *DeviceAddress
;
181 DEBUG ((DEBUG_VERBOSE
, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation
, (UINTN
)*DeviceAddress
, MapInfo
));
184 // If this is a read operation from the Bus Master's point of view,
185 // then copy the contents of the real buffer into the mapped buffer
186 // so the Bus Master can read the contents of the real buffer.
188 if (Operation
== EdkiiIoMmuOperationBusMasterRead
||
189 Operation
== EdkiiIoMmuOperationBusMasterRead64
) {
191 (VOID
*) (UINTN
) MapInfo
->DeviceAddress
,
192 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
193 MapInfo
->NumberOfBytes
201 Completes the Map() operation and releases any corresponding resources.
203 @param This The PPI instance pointer.
204 @param Mapping The mapping value returned from Map().
206 @retval EFI_SUCCESS The range was unmapped.
207 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
208 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
213 IN EDKII_IOMMU_PPI
*This
,
220 if (Mapping
== NULL
) {
224 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuUnmap - Mapping - %x\n", Mapping
));
225 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop
));
226 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom
));
229 ASSERT (MapInfo
->Signature
== MAP_INFO_SIGNATURE
);
230 DEBUG ((DEBUG_VERBOSE
, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo
->Operation
, (UINTN
)MapInfo
->DeviceAddress
, MapInfo
->NumberOfBytes
));
233 // If this is a write operation from the Bus Master's point of view,
234 // then copy the contents of the mapped buffer into the real buffer
235 // so the processor can read the contents of the real buffer.
237 if (MapInfo
->Operation
== EdkiiIoMmuOperationBusMasterWrite
||
238 MapInfo
->Operation
== EdkiiIoMmuOperationBusMasterWrite64
) {
240 (VOID
*) (UINTN
) MapInfo
->HostAddress
,
241 (VOID
*) (UINTN
) MapInfo
->DeviceAddress
,
242 MapInfo
->NumberOfBytes
246 Length
= MapInfo
->NumberOfBytes
+ sizeof(MAP_INFO
);
247 if (mDmaBufferCurrentBottom
== MapInfo
->DeviceAddress
+ Length
) {
248 mDmaBufferCurrentBottom
-= Length
;
255 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
256 OperationBusMasterCommonBuffer64 mapping.
258 @param This The PPI instance pointer.
259 @param MemoryType The type of memory to allocate, EfiBootServicesData or
260 EfiRuntimeServicesData.
261 @param Pages The number of pages to allocate.
262 @param HostAddress A pointer to store the base system memory address of the
264 @param Attributes The requested bit mask of attributes for the allocated range.
266 @retval EFI_SUCCESS The requested memory pages were allocated.
267 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
268 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
269 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
270 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
275 PeiIoMmuAllocateBuffer (
276 IN EDKII_IOMMU_PPI
*This
,
277 IN EFI_MEMORY_TYPE MemoryType
,
279 IN OUT VOID
**HostAddress
,
285 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuAllocateBuffer - page - %x\n", Pages
));
286 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop
));
287 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom
));
289 Length
= EFI_PAGES_TO_SIZE(Pages
);
290 if (Length
> mDmaBufferCurrentTop
- mDmaBufferCurrentBottom
) {
291 DEBUG ((DEBUG_ERROR
, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
293 return EFI_OUT_OF_RESOURCES
;
295 *HostAddress
= (VOID
*)(UINTN
)(mDmaBufferCurrentTop
- Length
);
296 mDmaBufferCurrentTop
-= Length
;
298 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress
));
303 Frees memory that was allocated with AllocateBuffer().
305 @param This The PPI instance pointer.
306 @param Pages The number of pages to free.
307 @param HostAddress The base system memory address of the allocated range.
309 @retval EFI_SUCCESS The requested memory pages were freed.
310 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
311 was not allocated with AllocateBuffer().
317 IN EDKII_IOMMU_PPI
*This
,
324 DEBUG ((DEBUG_VERBOSE
, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages
, HostAddress
));
325 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop
));
326 DEBUG ((DEBUG_VERBOSE
, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom
));
328 Length
= EFI_PAGES_TO_SIZE(Pages
);
329 if ((UINTN
)HostAddress
== mDmaBufferCurrentTop
) {
330 mDmaBufferCurrentTop
+= Length
;
336 EDKII_IOMMU_PPI mIoMmuPpi
= {
337 EDKII_IOMMU_PPI_REVISION
,
338 PeiIoMmuSetAttribute
,
341 PeiIoMmuAllocateBuffer
,
345 CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList
= {
346 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
351 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
352 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
353 EFI_RESOURCE_ATTRIBUTE_TESTED | \
354 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
355 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
356 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO \
359 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)
361 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)
363 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
365 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8
*mResourceTypeShortName
[] = {
376 Return the short name of resource type.
378 @param Type resource type.
380 @return the short name of resource type.
383 ShortNameOfResourceType (
387 if (Type
< sizeof(mResourceTypeShortName
) / sizeof(mResourceTypeShortName
[0])) {
388 return mResourceTypeShortName
[Type
];
397 @param HobList the HOB list.
404 EFI_PEI_HOB_POINTERS Hob
;
405 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
407 DEBUG ((DEBUG_VERBOSE
, "Resource Descriptor HOBs\n"));
408 for (Hob
.Raw
= HobList
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
409 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
410 ResourceHob
= Hob
.ResourceDescriptor
;
411 DEBUG ((DEBUG_VERBOSE
,
412 " BA=%016lx L=%016lx Attr=%08x ",
413 ResourceHob
->PhysicalStart
,
414 ResourceHob
->ResourceLength
,
415 ResourceHob
->ResourceAttribute
417 DEBUG ((DEBUG_VERBOSE
, ShortNameOfResourceType(ResourceHob
->ResourceType
)));
418 switch (ResourceHob
->ResourceType
) {
419 case EFI_RESOURCE_SYSTEM_MEMORY
:
420 if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_PERSISTENT
) != 0) {
421 DEBUG ((DEBUG_VERBOSE
, " (Persistent)"));
422 } else if ((ResourceHob
->ResourceAttribute
& EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE
) != 0) {
423 DEBUG ((DEBUG_VERBOSE
, " (MoreReliable)"));
424 } else if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == TESTED_MEMORY_ATTRIBUTES
) {
425 DEBUG ((DEBUG_VERBOSE
, " (Tested)"));
426 } else if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == INITIALIZED_MEMORY_ATTRIBUTES
) {
427 DEBUG ((DEBUG_VERBOSE
, " (Init)"));
428 } else if ((ResourceHob
->ResourceAttribute
& MEMORY_ATTRIBUTE_MASK
) == PRESENT_MEMORY_ATTRIBUTES
) {
429 DEBUG ((DEBUG_VERBOSE
, " (Present)"));
431 DEBUG ((DEBUG_VERBOSE
, " (Unknown)"));
437 DEBUG ((DEBUG_VERBOSE
, "\n"));
445 @param HobList the HOB list.
452 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
455 ASSERT(GET_HOB_TYPE(HobList
) == EFI_HOB_TYPE_HANDOFF
);
456 DEBUG ((DEBUG_VERBOSE
, "PHIT HOB\n"));
457 DEBUG ((DEBUG_VERBOSE
, " PhitHob - 0x%x\n", PhitHob
));
458 DEBUG ((DEBUG_VERBOSE
, " BootMode - 0x%x\n", PhitHob
->BootMode
));
459 DEBUG ((DEBUG_VERBOSE
, " EfiMemoryTop - 0x%016lx\n", PhitHob
->EfiMemoryTop
));
460 DEBUG ((DEBUG_VERBOSE
, " EfiMemoryBottom - 0x%016lx\n", PhitHob
->EfiMemoryBottom
));
461 DEBUG ((DEBUG_VERBOSE
, " EfiFreeMemoryTop - 0x%016lx\n", PhitHob
->EfiFreeMemoryTop
));
462 DEBUG ((DEBUG_VERBOSE
, " EfiFreeMemoryBottom - 0x%016lx\n", PhitHob
->EfiFreeMemoryBottom
));
463 DEBUG ((DEBUG_VERBOSE
, " EfiEndOfHobList - 0x%lx\n", PhitHob
->EfiEndOfHobList
));
467 Get the highest memory.
469 @return the highest memory.
477 EFI_PEI_HOB_POINTERS Hob
;
478 EFI_HOB_RESOURCE_DESCRIPTOR
*ResourceHob
;
482 HobList
= GetHobList ();
485 for (Hob
.Raw
= HobList
; !END_OF_HOB_LIST (Hob
); Hob
.Raw
= GET_NEXT_HOB (Hob
)) {
486 if (GET_HOB_TYPE (Hob
) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR
) {
487 ResourceHob
= Hob
.ResourceDescriptor
;
488 switch (ResourceHob
->ResourceType
) {
489 case EFI_RESOURCE_SYSTEM_MEMORY
:
490 ResourceTop
= ResourceHob
->PhysicalStart
+ ResourceHob
->ResourceLength
;
491 if (TopMemory
< ResourceTop
) {
492 TopMemory
= ResourceTop
;
498 DEBUG ((DEBUG_VERBOSE
, "\n"));
505 Initialize DMA protection.
507 @param DmaBufferSize the DMA buffer size
508 @param DmaBufferBase the DMA buffer base
510 @retval EFI_SUCCESS the DMA protection is initialized.
511 @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.
515 IN UINTN DmaBufferSize
,
516 OUT UINTN
*DmaBufferBase
521 EFI_HOB_HANDOFF_INFO_TABLE
*PhitHob
;
522 UINT32 LowMemoryAlignment
;
523 UINT64 HighMemoryAlignment
;
524 UINTN MemoryAlignment
;
530 HobList
= GetHobList ();
531 DumpPhitHob (HobList
);
532 DumpResourceHob (HobList
);
536 ASSERT (PhitHob
->EfiMemoryBottom
< PhitHob
->EfiMemoryTop
);
538 LowMemoryAlignment
= GetLowMemoryAlignment (mEngineMask
);
539 HighMemoryAlignment
= GetHighMemoryAlignment (mEngineMask
);
540 if (LowMemoryAlignment
< HighMemoryAlignment
) {
541 MemoryAlignment
= (UINTN
)HighMemoryAlignment
;
543 MemoryAlignment
= LowMemoryAlignment
;
545 ASSERT (DmaBufferSize
== ALIGN_VALUE(DmaBufferSize
, MemoryAlignment
));
546 *DmaBufferBase
= (UINTN
)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize
), MemoryAlignment
);
547 if (*DmaBufferBase
== 0) {
548 DEBUG ((DEBUG_INFO
, " InitDmaProtection : OutOfResource\n"));
549 return EFI_OUT_OF_RESOURCES
;
553 LowTop
= *DmaBufferBase
;
554 HighBottom
= *DmaBufferBase
+ DmaBufferSize
;
555 HighTop
= GetTopMemory ();
557 Status
= SetDmaProtectedRange (
560 (UINT32
)(LowTop
- LowBottom
),
565 if (EFI_ERROR(Status
)) {
566 FreePages ((VOID
*)*DmaBufferBase
, EFI_SIZE_TO_PAGES(DmaBufferSize
));
573 Dump DMAR DeviceScopeEntry.
575 @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
578 DumpDmarDeviceScopeEntry (
579 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*DmarDeviceScopeEntry
584 EFI_ACPI_DMAR_PCI_PATH
*PciPath
;
586 if (DmarDeviceScopeEntry
== NULL
) {
591 " *************************************************************************\n"
594 " * DMA-Remapping Device Scope Entry Structure *\n"
597 " *************************************************************************\n"
600 (sizeof(UINTN
) == sizeof(UINT64
)) ?
601 " DMAR Device Scope Entry address ...................... 0x%016lx\n" :
602 " DMAR Device Scope Entry address ...................... 0x%08x\n",
606 " Device Scope Entry Type ............................ 0x%02x\n",
607 DmarDeviceScopeEntry
->Type
609 switch (DmarDeviceScopeEntry
->Type
) {
610 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT
:
612 " PCI Endpoint Device\n"
615 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE
:
617 " PCI Sub-hierachy\n"
624 " Length ............................................. 0x%02x\n",
625 DmarDeviceScopeEntry
->Length
628 " Enumeration ID ..................................... 0x%02x\n",
629 DmarDeviceScopeEntry
->EnumerationId
632 " Starting Bus Number ................................ 0x%02x\n",
633 DmarDeviceScopeEntry
->StartBusNumber
636 PciPathNumber
= (DmarDeviceScopeEntry
->Length
- sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
)) / sizeof(EFI_ACPI_DMAR_PCI_PATH
);
637 PciPath
= (EFI_ACPI_DMAR_PCI_PATH
*)(DmarDeviceScopeEntry
+ 1);
638 for (PciPathIndex
= 0; PciPathIndex
< PciPathNumber
; PciPathIndex
++) {
640 " Device ............................................. 0x%02x\n",
641 PciPath
[PciPathIndex
].Device
644 " Function ........................................... 0x%02x\n",
645 PciPath
[PciPathIndex
].Function
650 " *************************************************************************\n\n"
657 Dump DMAR RMRR table.
659 @param[in] Rmrr DMAR RMRR table
663 IN EFI_ACPI_DMAR_RMRR_HEADER
*Rmrr
666 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*DmarDeviceScopeEntry
;
674 " ***************************************************************************\n"
677 " * Reserved Memory Region Reporting Structure *\n"
680 " ***************************************************************************\n"
683 (sizeof(UINTN
) == sizeof(UINT64
)) ?
684 " RMRR address ........................................... 0x%016lx\n" :
685 " RMRR address ........................................... 0x%08x\n",
689 " Type ................................................. 0x%04x\n",
693 " Length ............................................... 0x%04x\n",
697 " Segment Number ....................................... 0x%04x\n",
701 " Reserved Memory Region Base Address .................. 0x%016lx\n",
702 Rmrr
->ReservedMemoryRegionBaseAddress
705 " Reserved Memory Region Limit Address ................. 0x%016lx\n",
706 Rmrr
->ReservedMemoryRegionLimitAddress
709 RmrrLen
= Rmrr
->Header
.Length
- sizeof(EFI_ACPI_DMAR_RMRR_HEADER
);
710 DmarDeviceScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)(Rmrr
+ 1);
711 while (RmrrLen
> 0) {
712 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry
);
713 RmrrLen
-= DmarDeviceScopeEntry
->Length
;
714 DmarDeviceScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)((UINTN
)DmarDeviceScopeEntry
+ DmarDeviceScopeEntry
->Length
);
718 " ***************************************************************************\n\n"
725 Dump DMAR DRHD table.
727 @param[in] Drhd DMAR DRHD table
731 IN EFI_ACPI_DMAR_DRHD_HEADER
*Drhd
734 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*DmarDeviceScopeEntry
;
742 " ***************************************************************************\n"
745 " * DMA-Remapping Hardware Definition Structure *\n"
748 " ***************************************************************************\n"
751 (sizeof(UINTN
) == sizeof(UINT64
)) ?
752 " DRHD address ........................................... 0x%016lx\n" :
753 " DRHD address ........................................... 0x%08x\n",
757 " Type ................................................. 0x%04x\n",
761 " Length ............................................... 0x%04x\n",
765 " Flags ................................................ 0x%02x\n",
769 " INCLUDE_PCI_ALL .................................... 0x%02x\n",
770 Drhd
->Flags
& EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
773 " Segment Number ....................................... 0x%04x\n",
777 " Register Base Address ................................ 0x%016lx\n",
778 Drhd
->RegisterBaseAddress
781 DrhdLen
= Drhd
->Header
.Length
- sizeof(EFI_ACPI_DMAR_DRHD_HEADER
);
782 DmarDeviceScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)(Drhd
+ 1);
783 while (DrhdLen
> 0) {
784 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry
);
785 DrhdLen
-= DmarDeviceScopeEntry
->Length
;
786 DmarDeviceScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)((UINTN
)DmarDeviceScopeEntry
+ DmarDeviceScopeEntry
->Length
);
790 " ***************************************************************************\n\n"
797 Dump DMAR ACPI table.
799 @param[in] Dmar DMAR ACPI table
803 IN EFI_ACPI_DMAR_HEADER
*Dmar
806 EFI_ACPI_DMAR_STRUCTURE_HEADER
*DmarHeader
;
817 "*****************************************************************************\n"
823 "*****************************************************************************\n"
827 (sizeof(UINTN
) == sizeof(UINT64
)) ?
828 "DMAR address ............................................. 0x%016lx\n" :
829 "DMAR address ............................................. 0x%08x\n",
837 " Host Address Width ................................... 0x%02x\n",
838 Dmar
->HostAddressWidth
841 " Flags ................................................ 0x%02x\n",
845 " INTR_REMAP ......................................... 0x%02x\n",
846 Dmar
->Flags
& EFI_ACPI_DMAR_FLAGS_INTR_REMAP
849 " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
850 Dmar
->Flags
& EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
853 DmarLen
= Dmar
->Header
.Length
- sizeof(EFI_ACPI_DMAR_HEADER
);
854 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)(Dmar
+ 1);
855 while (DmarLen
> 0) {
856 switch (DmarHeader
->Type
) {
857 case EFI_ACPI_DMAR_TYPE_DRHD
:
858 DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER
*)DmarHeader
);
860 case EFI_ACPI_DMAR_TYPE_RMRR
:
861 DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER
*)DmarHeader
);
866 DmarLen
-= DmarHeader
->Length
;
867 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)DmarHeader
+ DmarHeader
->Length
);
871 "*****************************************************************************\n\n"
878 Get VTd engine number.
880 @return the VTd engine number.
887 EFI_ACPI_DMAR_STRUCTURE_HEADER
*DmarHeader
;
891 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)(mAcpiDmarTable
+ 1));
892 while ((UINTN
)DmarHeader
< (UINTN
)mAcpiDmarTable
+ mAcpiDmarTable
->Header
.Length
) {
893 switch (DmarHeader
->Type
) {
894 case EFI_ACPI_DMAR_TYPE_DRHD
:
900 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)DmarHeader
+ DmarHeader
->Length
);
906 Process DMAR DHRD table.
908 @param[in] VtdIndex The index of VTd engine.
909 @param[in] DmarDrhd The DRHD table.
914 IN EFI_ACPI_DMAR_DRHD_HEADER
*DmarDrhd
917 DEBUG ((DEBUG_INFO
," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex
, DmarDrhd
->RegisterBaseAddress
));
918 mVTdInfo
->VTdEngineAddress
[VtdIndex
] = DmarDrhd
->RegisterBaseAddress
;
922 Parse DMAR DRHD table.
924 @return EFI_SUCCESS The DMAR DRHD table is parsed.
927 ParseDmarAcpiTableDrhd (
931 EFI_ACPI_DMAR_STRUCTURE_HEADER
*DmarHeader
;
935 VtdUnitNumber
= GetVtdEngineNumber ();
936 if (VtdUnitNumber
== 0) {
937 return EFI_UNSUPPORTED
;
940 mVTdInfo
= AllocateZeroPool (sizeof(VTD_INFO
) + (VtdUnitNumber
- 1) * sizeof(UINT64
));
941 if (mVTdInfo
== NULL
) {
942 return EFI_OUT_OF_RESOURCES
;
944 mVTdInfo
->HostAddressWidth
= mAcpiDmarTable
->HostAddressWidth
;
945 mVTdInfo
->VTdEngineCount
= VtdUnitNumber
;
948 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)(mAcpiDmarTable
+ 1));
949 while ((UINTN
)DmarHeader
< (UINTN
)mAcpiDmarTable
+ mAcpiDmarTable
->Header
.Length
) {
950 switch (DmarHeader
->Type
) {
951 case EFI_ACPI_DMAR_TYPE_DRHD
:
952 ASSERT (VtdIndex
< VtdUnitNumber
);
953 ProcessDhrd (VtdIndex
, (EFI_ACPI_DMAR_DRHD_HEADER
*)DmarHeader
);
961 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)DmarHeader
+ DmarHeader
->Length
);
963 ASSERT (VtdIndex
== VtdUnitNumber
);
966 // Initialize the engine mask to all.
968 mEngineMask
= LShiftU64 (1, VtdUnitNumber
) - 1;
974 Return the VTd engine index according to the Segment and DevScopeEntry.
976 @param Segment The segment of the VTd engine
977 @param DevScopeEntry The DevScopeEntry of the VTd engine
979 @return The VTd engine index according to the Segment and DevScopeEntry.
980 @retval -1 The VTd engine is not found.
983 GetVTdEngineFromDevScopeEntry (
985 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*DevScopeEntry
988 EFI_ACPI_DMAR_STRUCTURE_HEADER
*DmarHeader
;
990 EFI_ACPI_DMAR_DRHD_HEADER
*DmarDrhd
;
991 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*ThisDevScopeEntry
;
994 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)(mAcpiDmarTable
+ 1));
995 while ((UINTN
)DmarHeader
< (UINTN
)mAcpiDmarTable
+ mAcpiDmarTable
->Header
.Length
) {
996 switch (DmarHeader
->Type
) {
997 case EFI_ACPI_DMAR_TYPE_DRHD
:
998 DmarDrhd
= (EFI_ACPI_DMAR_DRHD_HEADER
*)DmarHeader
;
999 if (DmarDrhd
->SegmentNumber
!= Segment
) {
1003 if ((DmarDrhd
->Header
.Length
== sizeof(EFI_ACPI_DMAR_DRHD_HEADER
)) ||
1004 ((DmarDrhd
->Flags
& EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
) != 0)) {
1006 // Do not handle PCI_ALL
1009 ThisDevScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)((UINTN
)(DmarDrhd
+ 1));
1010 while ((UINTN
)ThisDevScopeEntry
< (UINTN
)DmarDrhd
+ DmarDrhd
->Header
.Length
) {
1011 if ((ThisDevScopeEntry
->Length
== DevScopeEntry
->Length
) &&
1012 (CompareMem (ThisDevScopeEntry
, DevScopeEntry
, DevScopeEntry
->Length
) == 0)) {
1015 ThisDevScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)((UINTN
)ThisDevScopeEntry
+ ThisDevScopeEntry
->Length
);
1021 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)DmarHeader
+ DmarHeader
->Length
);
1027 Process DMAR RMRR table.
1029 @param[in] DmarRmrr The RMRR table.
1033 IN EFI_ACPI_DMAR_RMRR_HEADER
*DmarRmrr
1036 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*DmarDevScopeEntry
;
1044 DEBUG ((DEBUG_INFO
," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr
->ReservedMemoryRegionBaseAddress
, DmarRmrr
->ReservedMemoryRegionLimitAddress
));
1046 if ((DmarRmrr
->ReservedMemoryRegionBaseAddress
== 0) ||
1047 (DmarRmrr
->ReservedMemoryRegionLimitAddress
== 0)) {
1051 DmarDevScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)((UINTN
)(DmarRmrr
+ 1));
1052 while ((UINTN
)DmarDevScopeEntry
< (UINTN
)DmarRmrr
+ DmarRmrr
->Header
.Length
) {
1053 ASSERT (DmarDevScopeEntry
->Type
== EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT
);
1055 VTdIndex
= GetVTdEngineFromDevScopeEntry (DmarRmrr
->SegmentNumber
, DmarDevScopeEntry
);
1056 if (VTdIndex
!= (UINTN
)-1) {
1057 RmrrMask
= LShiftU64 (1, VTdIndex
);
1060 LowTop
= (UINTN
)DmarRmrr
->ReservedMemoryRegionBaseAddress
;
1061 HighBottom
= (UINTN
)DmarRmrr
->ReservedMemoryRegionLimitAddress
+ 1;
1062 HighTop
= GetTopMemory ();
1064 SetDmaProtectedRange (
1067 (UINT32
)(LowTop
- LowBottom
),
1069 HighTop
- HighBottom
1073 // Remove the engine from the engine mask.
1074 // The assumption is that any other PEI driver does not access
1075 // the device covered by this engine.
1077 mEngineMask
= mEngineMask
& (~RmrrMask
);
1080 DmarDevScopeEntry
= (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
*)((UINTN
)DmarDevScopeEntry
+ DmarDevScopeEntry
->Length
);
1085 Parse DMAR DRHD table.
1088 ParseDmarAcpiTableRmrr (
1092 EFI_ACPI_DMAR_STRUCTURE_HEADER
*DmarHeader
;
1094 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)(mAcpiDmarTable
+ 1));
1095 while ((UINTN
)DmarHeader
< (UINTN
)mAcpiDmarTable
+ mAcpiDmarTable
->Header
.Length
) {
1096 switch (DmarHeader
->Type
) {
1097 case EFI_ACPI_DMAR_TYPE_RMRR
:
1098 ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER
*)DmarHeader
);
1103 DmarHeader
= (EFI_ACPI_DMAR_STRUCTURE_HEADER
*)((UINTN
)DmarHeader
+ DmarHeader
->Length
);
1108 Initializes the Intel VTd PMR PEIM.
1110 @param FileHandle Handle of the file being invoked.
1111 @param PeiServices Describes the list of possible PEI Services.
1113 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
1114 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
1119 IntelVTdPmrInitialize (
1120 IN EFI_PEI_FILE_HANDLE FileHandle
,
1121 IN CONST EFI_PEI_SERVICES
**PeiServices
1126 if ((PcdGet8(PcdVTdPolicyPropertyMask
) & BIT0
) == 0) {
1127 return EFI_UNSUPPORTED
;
1130 Status
= PeiServicesLocatePpi (
1131 &gEdkiiVTdInfoPpiGuid
,
1134 (VOID
**)&mAcpiDmarTable
1136 ASSERT_EFI_ERROR(Status
);
1138 DumpAcpiDMAR (mAcpiDmarTable
);
1141 // Get DMAR information to local VTdInfo
1143 Status
= ParseDmarAcpiTableDrhd ();
1144 if (EFI_ERROR(Status
)) {
1149 // If there is RMRR memory, parse it here.
1151 ParseDmarAcpiTableRmrr ();
1154 // Find a pre-memory in resource hob as DMA buffer
1155 // Mark PEI memory to be DMA protected.
1157 Status
= InitDmaProtection (mDmaBufferSize
, &mDmaBufferBase
);
1158 if (EFI_ERROR(Status
)) {
1162 DEBUG ((DEBUG_INFO
, " DmaBufferBase : 0x%x\n", mDmaBufferBase
));
1163 DEBUG ((DEBUG_INFO
, " DmaBufferSize : 0x%x\n", mDmaBufferSize
));
1165 mDmaBufferCurrentTop
= mDmaBufferBase
+ mDmaBufferSize
;
1166 mDmaBufferCurrentBottom
= mDmaBufferBase
;
1171 Status
= PeiServicesInstallPpi (&mIoMmuPpiList
);
1172 ASSERT_EFI_ERROR(Status
);