e7682749a6b01106690d8af37256db9e104b9c8d
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / IntelVTdPmrPei.c
1 /** @file
2
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4
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
9
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.
12
13 **/
14
15 #include <Uefi.h>
16 #include <PiPei.h>
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
28 #include "IntelVTdPmrPei.h"
29
30 #define TOTAL_DMA_BUFFER_SIZE SIZE_4MB
31
32 EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;
33 VTD_INFO *mVTdInfo;
34 UINT64 mEngineMask;
35 UINTN mDmaBufferBase;
36 UINTN mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
37 UINTN mDmaBufferCurrentTop;
38 UINTN mDmaBufferCurrentBottom;
39
40 #define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
41 typedef struct {
42 UINT32 Signature;
43 EDKII_IOMMU_OPERATION Operation;
44 UINTN NumberOfBytes;
45 EFI_PHYSICAL_ADDRESS HostAddress;
46 EFI_PHYSICAL_ADDRESS DeviceAddress;
47 } MAP_INFO;
48
49 /**
50
51 PEI Memory Layout:
52
53 +------------------+ <=============== PHMR.Limit (Top of memory)
54 | Mem Resource |
55 | |
56
57 +------------------+ <------- EfiMemoryTop
58 | PEI allocated |
59 =========== +==================+ <=============== PHMR.Base
60 ^ | Commom Buf |
61 | | -------------- |
62 DMA Buffer | * DMA FREE * |
63 | | -------------- |
64 V | Read/Write Buf |
65 =========== +==================+ <=============== PLMR.Limit
66 | PEI allocated |
67 | -------------- | <------- EfiFreeMemoryTop
68 | * PEI FREE * |
69 | -------------- | <------- EfiFreeMemoryBottom
70 | hob |
71 | -------------- |
72 | Stack |
73 +------------------+ <------- EfiMemoryBottom / Stack Bottom
74
75 +------------------+
76 | Mem Alloc Hob |
77 +------------------+
78
79 | |
80 | Mem Resource |
81 +------------------+ <=============== PLMR.Base (0)
82 **/
83
84
85 /**
86 Set IOMMU attribute for a system memory.
87
88 If the IOMMU PPI exists, the system memory cannot be used
89 for DMA by default.
90
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).
94
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.
98
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.
106
107 **/
108 EFI_STATUS
109 EFIAPI
110 PeiIoMmuSetAttribute (
111 IN EDKII_IOMMU_PPI *This,
112 IN VOID *Mapping,
113 IN UINT64 IoMmuAccess
114 )
115 {
116 return EFI_SUCCESS;
117 }
118
119 /**
120 Provides the controller-specific addresses required to access system memory from a
121 DMA bus master.
122
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
127 that were mapped.
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().
131
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.
137
138 **/
139 EFI_STATUS
140 EFIAPI
141 PeiIoMmuMap (
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,
147 OUT VOID **Mapping
148 )
149 {
150 MAP_INFO *MapInfo;
151 UINTN Length;
152
153 if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
154 Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
155 *DeviceAddress = (UINTN)HostAddress;
156 *Mapping = 0;
157 return EFI_SUCCESS;
158 }
159
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));
163
164 Length = *NumberOfBytes + sizeof(MAP_INFO);
165 if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
166 DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
167 ASSERT (FALSE);
168 return EFI_OUT_OF_RESOURCES;
169 }
170
171 *DeviceAddress = mDmaBufferCurrentBottom;
172 mDmaBufferCurrentBottom += Length;
173
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;
180 *Mapping = MapInfo;
181 DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation, (UINTN)*DeviceAddress, MapInfo));
182
183 //
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.
187 //
188 if (Operation == EdkiiIoMmuOperationBusMasterRead ||
189 Operation == EdkiiIoMmuOperationBusMasterRead64) {
190 CopyMem (
191 (VOID *) (UINTN) MapInfo->DeviceAddress,
192 (VOID *) (UINTN) MapInfo->HostAddress,
193 MapInfo->NumberOfBytes
194 );
195 }
196
197 return EFI_SUCCESS;
198 }
199
200 /**
201 Completes the Map() operation and releases any corresponding resources.
202
203 @param This The PPI instance pointer.
204 @param Mapping The mapping value returned from Map().
205
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.
209 **/
210 EFI_STATUS
211 EFIAPI
212 PeiIoMmuUnmap (
213 IN EDKII_IOMMU_PPI *This,
214 IN VOID *Mapping
215 )
216 {
217 MAP_INFO *MapInfo;
218 UINTN Length;
219
220 if (Mapping == NULL) {
221 return EFI_SUCCESS;
222 }
223
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));
227
228 MapInfo = Mapping;
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));
231
232 //
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.
236 //
237 if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
238 MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
239 CopyMem (
240 (VOID *) (UINTN) MapInfo->HostAddress,
241 (VOID *) (UINTN) MapInfo->DeviceAddress,
242 MapInfo->NumberOfBytes
243 );
244 }
245
246 Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
247 if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
248 mDmaBufferCurrentBottom -= Length;
249 }
250
251 return EFI_SUCCESS;
252 }
253
254 /**
255 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
256 OperationBusMasterCommonBuffer64 mapping.
257
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
263 allocated range.
264 @param Attributes The requested bit mask of attributes for the allocated range.
265
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.
271
272 **/
273 EFI_STATUS
274 EFIAPI
275 PeiIoMmuAllocateBuffer (
276 IN EDKII_IOMMU_PPI *This,
277 IN EFI_MEMORY_TYPE MemoryType,
278 IN UINTN Pages,
279 IN OUT VOID **HostAddress,
280 IN UINT64 Attributes
281 )
282 {
283 UINTN Length;
284
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));
288
289 Length = EFI_PAGES_TO_SIZE(Pages);
290 if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
291 DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
292 ASSERT (FALSE);
293 return EFI_OUT_OF_RESOURCES;
294 }
295 *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);
296 mDmaBufferCurrentTop -= Length;
297
298 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
299 return EFI_SUCCESS;
300 }
301
302 /**
303 Frees memory that was allocated with AllocateBuffer().
304
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.
308
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().
312
313 **/
314 EFI_STATUS
315 EFIAPI
316 PeiIoMmuFreeBuffer (
317 IN EDKII_IOMMU_PPI *This,
318 IN UINTN Pages,
319 IN VOID *HostAddress
320 )
321 {
322 UINTN Length;
323
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));
327
328 Length = EFI_PAGES_TO_SIZE(Pages);
329 if ((UINTN)HostAddress == mDmaBufferCurrentTop) {
330 mDmaBufferCurrentTop += Length;
331 }
332
333 return EFI_SUCCESS;
334 }
335
336 EDKII_IOMMU_PPI mIoMmuPpi = {
337 EDKII_IOMMU_PPI_REVISION,
338 PeiIoMmuSetAttribute,
339 PeiIoMmuMap,
340 PeiIoMmuUnmap,
341 PeiIoMmuAllocateBuffer,
342 PeiIoMmuFreeBuffer,
343 };
344
345 CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
346 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
347 &gEdkiiIoMmuPpiGuid,
348 (VOID *) &mIoMmuPpi
349 };
350
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 \
357 )
358
359 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)
360
361 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)
362
363 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
364
365 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mResourceTypeShortName[] = {
366 "Mem",
367 "MMIO",
368 "I/O",
369 "FD",
370 "MM Port I/O",
371 "Reserved Mem",
372 "Reserved I/O",
373 };
374
375 /**
376 Return the short name of resource type.
377
378 @param Type resource type.
379
380 @return the short name of resource type.
381 **/
382 CHAR8 *
383 ShortNameOfResourceType (
384 IN UINT32 Type
385 )
386 {
387 if (Type < sizeof(mResourceTypeShortName) / sizeof(mResourceTypeShortName[0])) {
388 return mResourceTypeShortName[Type];
389 } else {
390 return "Unknown";
391 }
392 }
393
394 /**
395 Dump resource hob.
396
397 @param HobList the HOB list.
398 **/
399 VOID
400 DumpResourceHob (
401 IN VOID *HobList
402 )
403 {
404 EFI_PEI_HOB_POINTERS Hob;
405 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
406
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
416 ));
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)"));
430 } else {
431 DEBUG ((DEBUG_VERBOSE, " (Unknown)"));
432 }
433 break;
434 default:
435 break;
436 }
437 DEBUG ((DEBUG_VERBOSE, "\n"));
438 }
439 }
440 }
441
442 /**
443 Dump PHIT hob.
444
445 @param HobList the HOB list.
446 **/
447 VOID
448 DumpPhitHob (
449 IN VOID *HobList
450 )
451 {
452 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
453
454 PhitHob = HobList;
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));
464 }
465
466 /**
467 Get the highest memory.
468
469 @return the highest memory.
470 **/
471 UINT64
472 GetTopMemory (
473 VOID
474 )
475 {
476 VOID *HobList;
477 EFI_PEI_HOB_POINTERS Hob;
478 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
479 UINT64 TopMemory;
480 UINT64 ResourceTop;
481
482 HobList = GetHobList ();
483
484 TopMemory = 0;
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;
493 }
494 break;
495 default:
496 break;
497 }
498 DEBUG ((DEBUG_VERBOSE, "\n"));
499 }
500 }
501 return TopMemory;
502 }
503
504 /**
505 Initialize DMA protection.
506
507 @param DmaBufferSize the DMA buffer size
508 @param DmaBufferBase the DMA buffer base
509
510 @retval EFI_SUCCESS the DMA protection is initialized.
511 @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.
512 **/
513 EFI_STATUS
514 InitDmaProtection (
515 IN UINTN DmaBufferSize,
516 OUT UINTN *DmaBufferBase
517 )
518 {
519 EFI_STATUS Status;
520 VOID *HobList;
521 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
522 UINT32 LowMemoryAlignment;
523 UINT64 HighMemoryAlignment;
524 UINTN MemoryAlignment;
525 UINTN LowBottom;
526 UINTN LowTop;
527 UINTN HighBottom;
528 UINT64 HighTop;
529
530 HobList = GetHobList ();
531 DumpPhitHob (HobList);
532 DumpResourceHob (HobList);
533
534 PhitHob = HobList;
535
536 ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
537
538 LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);
539 HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
540 if (LowMemoryAlignment < HighMemoryAlignment) {
541 MemoryAlignment = (UINTN)HighMemoryAlignment;
542 } else {
543 MemoryAlignment = LowMemoryAlignment;
544 }
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;
550 }
551
552 LowBottom = 0;
553 LowTop = *DmaBufferBase;
554 HighBottom = *DmaBufferBase + DmaBufferSize;
555 HighTop = GetTopMemory ();
556
557 Status = SetDmaProtectedRange (
558 mEngineMask,
559 (UINT32)LowBottom,
560 (UINT32)(LowTop - LowBottom),
561 HighBottom,
562 HighTop - HighBottom
563 );
564
565 if (EFI_ERROR(Status)) {
566 FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));
567 }
568
569 return Status;
570 }
571
572 /**
573 Dump DMAR DeviceScopeEntry.
574
575 @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
576 **/
577 VOID
578 DumpDmarDeviceScopeEntry (
579 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
580 )
581 {
582 UINTN PciPathNumber;
583 UINTN PciPathIndex;
584 EFI_ACPI_DMAR_PCI_PATH *PciPath;
585
586 if (DmarDeviceScopeEntry == NULL) {
587 return;
588 }
589
590 DEBUG ((DEBUG_INFO,
591 " *************************************************************************\n"
592 ));
593 DEBUG ((DEBUG_INFO,
594 " * DMA-Remapping Device Scope Entry Structure *\n"
595 ));
596 DEBUG ((DEBUG_INFO,
597 " *************************************************************************\n"
598 ));
599 DEBUG ((DEBUG_INFO,
600 (sizeof(UINTN) == sizeof(UINT64)) ?
601 " DMAR Device Scope Entry address ...................... 0x%016lx\n" :
602 " DMAR Device Scope Entry address ...................... 0x%08x\n",
603 DmarDeviceScopeEntry
604 ));
605 DEBUG ((DEBUG_INFO,
606 " Device Scope Entry Type ............................ 0x%02x\n",
607 DmarDeviceScopeEntry->Type
608 ));
609 switch (DmarDeviceScopeEntry->Type) {
610 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
611 DEBUG ((DEBUG_INFO,
612 " PCI Endpoint Device\n"
613 ));
614 break;
615 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
616 DEBUG ((DEBUG_INFO,
617 " PCI Sub-hierachy\n"
618 ));
619 break;
620 default:
621 break;
622 }
623 DEBUG ((DEBUG_INFO,
624 " Length ............................................. 0x%02x\n",
625 DmarDeviceScopeEntry->Length
626 ));
627 DEBUG ((DEBUG_INFO,
628 " Enumeration ID ..................................... 0x%02x\n",
629 DmarDeviceScopeEntry->EnumerationId
630 ));
631 DEBUG ((DEBUG_INFO,
632 " Starting Bus Number ................................ 0x%02x\n",
633 DmarDeviceScopeEntry->StartBusNumber
634 ));
635
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++) {
639 DEBUG ((DEBUG_INFO,
640 " Device ............................................. 0x%02x\n",
641 PciPath[PciPathIndex].Device
642 ));
643 DEBUG ((DEBUG_INFO,
644 " Function ........................................... 0x%02x\n",
645 PciPath[PciPathIndex].Function
646 ));
647 }
648
649 DEBUG ((DEBUG_INFO,
650 " *************************************************************************\n\n"
651 ));
652
653 return;
654 }
655
656 /**
657 Dump DMAR RMRR table.
658
659 @param[in] Rmrr DMAR RMRR table
660 **/
661 VOID
662 DumpDmarRmrr (
663 IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
664 )
665 {
666 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
667 INTN RmrrLen;
668
669 if (Rmrr == NULL) {
670 return;
671 }
672
673 DEBUG ((DEBUG_INFO,
674 " ***************************************************************************\n"
675 ));
676 DEBUG ((DEBUG_INFO,
677 " * Reserved Memory Region Reporting Structure *\n"
678 ));
679 DEBUG ((DEBUG_INFO,
680 " ***************************************************************************\n"
681 ));
682 DEBUG ((DEBUG_INFO,
683 (sizeof(UINTN) == sizeof(UINT64)) ?
684 " RMRR address ........................................... 0x%016lx\n" :
685 " RMRR address ........................................... 0x%08x\n",
686 Rmrr
687 ));
688 DEBUG ((DEBUG_INFO,
689 " Type ................................................. 0x%04x\n",
690 Rmrr->Header.Type
691 ));
692 DEBUG ((DEBUG_INFO,
693 " Length ............................................... 0x%04x\n",
694 Rmrr->Header.Length
695 ));
696 DEBUG ((DEBUG_INFO,
697 " Segment Number ....................................... 0x%04x\n",
698 Rmrr->SegmentNumber
699 ));
700 DEBUG ((DEBUG_INFO,
701 " Reserved Memory Region Base Address .................. 0x%016lx\n",
702 Rmrr->ReservedMemoryRegionBaseAddress
703 ));
704 DEBUG ((DEBUG_INFO,
705 " Reserved Memory Region Limit Address ................. 0x%016lx\n",
706 Rmrr->ReservedMemoryRegionLimitAddress
707 ));
708
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);
715 }
716
717 DEBUG ((DEBUG_INFO,
718 " ***************************************************************************\n\n"
719 ));
720
721 return;
722 }
723
724 /**
725 Dump DMAR DRHD table.
726
727 @param[in] Drhd DMAR DRHD table
728 **/
729 VOID
730 DumpDmarDrhd (
731 IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
732 )
733 {
734 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
735 INTN DrhdLen;
736
737 if (Drhd == NULL) {
738 return;
739 }
740
741 DEBUG ((DEBUG_INFO,
742 " ***************************************************************************\n"
743 ));
744 DEBUG ((DEBUG_INFO,
745 " * DMA-Remapping Hardware Definition Structure *\n"
746 ));
747 DEBUG ((DEBUG_INFO,
748 " ***************************************************************************\n"
749 ));
750 DEBUG ((DEBUG_INFO,
751 (sizeof(UINTN) == sizeof(UINT64)) ?
752 " DRHD address ........................................... 0x%016lx\n" :
753 " DRHD address ........................................... 0x%08x\n",
754 Drhd
755 ));
756 DEBUG ((DEBUG_INFO,
757 " Type ................................................. 0x%04x\n",
758 Drhd->Header.Type
759 ));
760 DEBUG ((DEBUG_INFO,
761 " Length ............................................... 0x%04x\n",
762 Drhd->Header.Length
763 ));
764 DEBUG ((DEBUG_INFO,
765 " Flags ................................................ 0x%02x\n",
766 Drhd->Flags
767 ));
768 DEBUG ((DEBUG_INFO,
769 " INCLUDE_PCI_ALL .................................... 0x%02x\n",
770 Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
771 ));
772 DEBUG ((DEBUG_INFO,
773 " Segment Number ....................................... 0x%04x\n",
774 Drhd->SegmentNumber
775 ));
776 DEBUG ((DEBUG_INFO,
777 " Register Base Address ................................ 0x%016lx\n",
778 Drhd->RegisterBaseAddress
779 ));
780
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);
787 }
788
789 DEBUG ((DEBUG_INFO,
790 " ***************************************************************************\n\n"
791 ));
792
793 return;
794 }
795
796 /**
797 Dump DMAR ACPI table.
798
799 @param[in] Dmar DMAR ACPI table
800 **/
801 VOID
802 DumpAcpiDMAR (
803 IN EFI_ACPI_DMAR_HEADER *Dmar
804 )
805 {
806 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
807 INTN DmarLen;
808
809 if (Dmar == NULL) {
810 return;
811 }
812
813 //
814 // Dump Dmar table
815 //
816 DEBUG ((DEBUG_INFO,
817 "*****************************************************************************\n"
818 ));
819 DEBUG ((DEBUG_INFO,
820 "* DMAR Table *\n"
821 ));
822 DEBUG ((DEBUG_INFO,
823 "*****************************************************************************\n"
824 ));
825
826 DEBUG ((DEBUG_INFO,
827 (sizeof(UINTN) == sizeof(UINT64)) ?
828 "DMAR address ............................................. 0x%016lx\n" :
829 "DMAR address ............................................. 0x%08x\n",
830 Dmar
831 ));
832
833 DEBUG ((DEBUG_INFO,
834 " Table Contents:\n"
835 ));
836 DEBUG ((DEBUG_INFO,
837 " Host Address Width ................................... 0x%02x\n",
838 Dmar->HostAddressWidth
839 ));
840 DEBUG ((DEBUG_INFO,
841 " Flags ................................................ 0x%02x\n",
842 Dmar->Flags
843 ));
844 DEBUG ((DEBUG_INFO,
845 " INTR_REMAP ......................................... 0x%02x\n",
846 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
847 ));
848 DEBUG ((DEBUG_INFO,
849 " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
850 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
851 ));
852
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);
859 break;
860 case EFI_ACPI_DMAR_TYPE_RMRR:
861 DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
862 break;
863 default:
864 break;
865 }
866 DmarLen -= DmarHeader->Length;
867 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
868 }
869
870 DEBUG ((DEBUG_INFO,
871 "*****************************************************************************\n\n"
872 ));
873
874 return;
875 }
876
877 /**
878 Get VTd engine number.
879
880 @return the VTd engine number.
881 **/
882 UINTN
883 GetVtdEngineNumber (
884 VOID
885 )
886 {
887 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
888 UINTN VtdIndex;
889
890 VtdIndex = 0;
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:
895 VtdIndex++;
896 break;
897 default:
898 break;
899 }
900 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
901 }
902 return VtdIndex ;
903 }
904
905 /**
906 Process DMAR DHRD table.
907
908 @param[in] VtdIndex The index of VTd engine.
909 @param[in] DmarDrhd The DRHD table.
910 **/
911 VOID
912 ProcessDhrd (
913 IN UINTN VtdIndex,
914 IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
915 )
916 {
917 DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
918 mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
919 }
920
921 /**
922 Parse DMAR DRHD table.
923
924 @return EFI_SUCCESS The DMAR DRHD table is parsed.
925 **/
926 EFI_STATUS
927 ParseDmarAcpiTableDrhd (
928 VOID
929 )
930 {
931 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
932 UINTN VtdUnitNumber;
933 UINTN VtdIndex;
934
935 VtdUnitNumber = GetVtdEngineNumber ();
936 if (VtdUnitNumber == 0) {
937 return EFI_UNSUPPORTED;
938 }
939
940 mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
941 if (mVTdInfo == NULL) {
942 return EFI_OUT_OF_RESOURCES;
943 }
944 mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
945 mVTdInfo->VTdEngineCount = VtdUnitNumber;
946
947 VtdIndex = 0;
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);
954 VtdIndex++;
955
956 break;
957
958 default:
959 break;
960 }
961 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
962 }
963 ASSERT (VtdIndex == VtdUnitNumber);
964
965 //
966 // Initialize the engine mask to all.
967 //
968 mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
969
970 return EFI_SUCCESS;
971 }
972
973 /**
974 Return the VTd engine index according to the Segment and DevScopeEntry.
975
976 @param Segment The segment of the VTd engine
977 @param DevScopeEntry The DevScopeEntry of the VTd engine
978
979 @return The VTd engine index according to the Segment and DevScopeEntry.
980 @retval -1 The VTd engine is not found.
981 **/
982 UINTN
983 GetVTdEngineFromDevScopeEntry (
984 IN UINT16 Segment,
985 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
986 )
987 {
988 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
989 UINTN VtdIndex;
990 EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;
991 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;
992
993 VtdIndex = 0;
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) {
1000 // Mismatch
1001 break;
1002 }
1003 if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
1004 ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
1005 // No DevScopeEntry
1006 // Do not handle PCI_ALL
1007 break;
1008 }
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)) {
1013 return VtdIndex;
1014 }
1015 ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
1016 }
1017 break;
1018 default:
1019 break;
1020 }
1021 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
1022 }
1023 return (UINTN)-1;
1024 }
1025
1026 /**
1027 Process DMAR RMRR table.
1028
1029 @param[in] DmarRmrr The RMRR table.
1030 **/
1031 VOID
1032 ProcessRmrr (
1033 IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
1034 )
1035 {
1036 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
1037 UINTN VTdIndex;
1038 UINT64 RmrrMask;
1039 UINTN LowBottom;
1040 UINTN LowTop;
1041 UINTN HighBottom;
1042 UINT64 HighTop;
1043
1044 DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
1045
1046 if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
1047 (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
1048 return ;
1049 }
1050
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);
1054
1055 VTdIndex = GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, DmarDevScopeEntry);
1056 if (VTdIndex != (UINTN)-1) {
1057 RmrrMask = LShiftU64 (1, VTdIndex);
1058
1059 LowBottom = 0;
1060 LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
1061 HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
1062 HighTop = GetTopMemory ();
1063
1064 SetDmaProtectedRange (
1065 RmrrMask,
1066 0,
1067 (UINT32)(LowTop - LowBottom),
1068 HighBottom,
1069 HighTop - HighBottom
1070 );
1071
1072 //
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.
1076 //
1077 mEngineMask = mEngineMask & (~RmrrMask);
1078 }
1079
1080 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
1081 }
1082 }
1083
1084 /**
1085 Parse DMAR DRHD table.
1086 **/
1087 VOID
1088 ParseDmarAcpiTableRmrr (
1089 VOID
1090 )
1091 {
1092 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
1093
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);
1099 break;
1100 default:
1101 break;
1102 }
1103 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
1104 }
1105 }
1106
1107 /**
1108 Initializes the Intel VTd PMR PEIM.
1109
1110 @param FileHandle Handle of the file being invoked.
1111 @param PeiServices Describes the list of possible PEI Services.
1112
1113 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
1114 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
1115
1116 **/
1117 EFI_STATUS
1118 EFIAPI
1119 IntelVTdPmrInitialize (
1120 IN EFI_PEI_FILE_HANDLE FileHandle,
1121 IN CONST EFI_PEI_SERVICES **PeiServices
1122 )
1123 {
1124 EFI_STATUS Status;
1125
1126 if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
1127 return EFI_UNSUPPORTED;
1128 }
1129
1130 Status = PeiServicesLocatePpi (
1131 &gEdkiiVTdInfoPpiGuid,
1132 0,
1133 NULL,
1134 (VOID **)&mAcpiDmarTable
1135 );
1136 ASSERT_EFI_ERROR(Status);
1137
1138 DumpAcpiDMAR (mAcpiDmarTable);
1139
1140 //
1141 // Get DMAR information to local VTdInfo
1142 //
1143 Status = ParseDmarAcpiTableDrhd ();
1144 if (EFI_ERROR(Status)) {
1145 return Status;
1146 }
1147
1148 //
1149 // If there is RMRR memory, parse it here.
1150 //
1151 ParseDmarAcpiTableRmrr ();
1152
1153 //
1154 // Find a pre-memory in resource hob as DMA buffer
1155 // Mark PEI memory to be DMA protected.
1156 //
1157 Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);
1158 if (EFI_ERROR(Status)) {
1159 return Status;
1160 }
1161
1162 DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));
1163 DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));
1164
1165 mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;
1166 mDmaBufferCurrentBottom = mDmaBufferBase;
1167
1168 //
1169 // Install PPI.
1170 //
1171 Status = PeiServicesInstallPpi (&mIoMmuPpiList);
1172 ASSERT_EFI_ERROR(Status);
1173
1174 return Status;
1175 }
1176