]> git.proxmox.com Git - mirror_edk2.git/blob - IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
3fe6d654cd2026225d5a0606d6c5ed9e78b6cf14
[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 #include <Ppi/EndOfPeiPhase.h>
28
29 #include "IntelVTdPmrPei.h"
30
31 #define TOTAL_DMA_BUFFER_SIZE SIZE_4MB
32 #define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB
33
34 EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;
35 VTD_INFO *mVTdInfo;
36 UINT64 mEngineMask;
37 UINTN mDmaBufferBase;
38 UINTN mDmaBufferSize;
39 UINTN mDmaBufferCurrentTop;
40 UINTN mDmaBufferCurrentBottom;
41
42 #define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
43 typedef struct {
44 UINT32 Signature;
45 EDKII_IOMMU_OPERATION Operation;
46 UINTN NumberOfBytes;
47 EFI_PHYSICAL_ADDRESS HostAddress;
48 EFI_PHYSICAL_ADDRESS DeviceAddress;
49 } MAP_INFO;
50
51 /**
52
53 PEI Memory Layout:
54
55 +------------------+ <=============== PHMR.Limit (Top of memory)
56 | Mem Resource |
57 | |
58
59 +------------------+ <------- EfiMemoryTop
60 | PEI allocated |
61 =========== +==================+ <=============== PHMR.Base
62 ^ | Commom Buf |
63 | | -------------- |
64 DMA Buffer | * DMA FREE * |
65 | | -------------- |
66 V | Read/Write Buf |
67 =========== +==================+ <=============== PLMR.Limit
68 | PEI allocated |
69 | -------------- | <------- EfiFreeMemoryTop
70 | * PEI FREE * |
71 | -------------- | <------- EfiFreeMemoryBottom
72 | hob |
73 | -------------- |
74 | Stack |
75 +------------------+ <------- EfiMemoryBottom / Stack Bottom
76
77 +------------------+
78 | Mem Alloc Hob |
79 +------------------+
80
81 | |
82 | Mem Resource |
83 +------------------+ <=============== PLMR.Base (0)
84 **/
85
86
87 /**
88 Set IOMMU attribute for a system memory.
89
90 If the IOMMU PPI exists, the system memory cannot be used
91 for DMA by default.
92
93 When a device requests a DMA access for a system memory,
94 the device driver need use SetAttribute() to update the IOMMU
95 attribute to request DMA access (read and/or write).
96
97 @param[in] This The PPI instance pointer.
98 @param[in] Mapping The mapping value returned from Map().
99 @param[in] IoMmuAccess The IOMMU access.
100
101 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
102 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
103 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
104 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
105 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping.
106 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
107 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
108
109 **/
110 EFI_STATUS
111 EFIAPI
112 PeiIoMmuSetAttribute (
113 IN EDKII_IOMMU_PPI *This,
114 IN VOID *Mapping,
115 IN UINT64 IoMmuAccess
116 )
117 {
118 return EFI_SUCCESS;
119 }
120
121 /**
122 Provides the controller-specific addresses required to access system memory from a
123 DMA bus master.
124
125 @param This The PPI instance pointer.
126 @param Operation Indicates if the bus master is going to read or write to system memory.
127 @param HostAddress The system memory address to map to the PCI controller.
128 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
129 that were mapped.
130 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
131 access the hosts HostAddress.
132 @param Mapping A resulting value to pass to Unmap().
133
134 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
135 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
136 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
137 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
138 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
139
140 **/
141 EFI_STATUS
142 EFIAPI
143 PeiIoMmuMap (
144 IN EDKII_IOMMU_PPI *This,
145 IN EDKII_IOMMU_OPERATION Operation,
146 IN VOID *HostAddress,
147 IN OUT UINTN *NumberOfBytes,
148 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
149 OUT VOID **Mapping
150 )
151 {
152 MAP_INFO *MapInfo;
153 UINTN Length;
154
155 if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
156 Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
157 *DeviceAddress = (UINTN)HostAddress;
158 *Mapping = 0;
159 return EFI_SUCCESS;
160 }
161
162 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));
163 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
164 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
165
166 Length = *NumberOfBytes + sizeof(MAP_INFO);
167 if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
168 DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
169 ASSERT (FALSE);
170 return EFI_OUT_OF_RESOURCES;
171 }
172
173 *DeviceAddress = mDmaBufferCurrentBottom;
174 mDmaBufferCurrentBottom += Length;
175
176 MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);
177 MapInfo->Signature = MAP_INFO_SIGNATURE;
178 MapInfo->Operation = Operation;
179 MapInfo->NumberOfBytes = *NumberOfBytes;
180 MapInfo->HostAddress = (UINTN)HostAddress;
181 MapInfo->DeviceAddress = *DeviceAddress;
182 *Mapping = MapInfo;
183 DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation, (UINTN)*DeviceAddress, MapInfo));
184
185 //
186 // If this is a read operation from the Bus Master's point of view,
187 // then copy the contents of the real buffer into the mapped buffer
188 // so the Bus Master can read the contents of the real buffer.
189 //
190 if (Operation == EdkiiIoMmuOperationBusMasterRead ||
191 Operation == EdkiiIoMmuOperationBusMasterRead64) {
192 CopyMem (
193 (VOID *) (UINTN) MapInfo->DeviceAddress,
194 (VOID *) (UINTN) MapInfo->HostAddress,
195 MapInfo->NumberOfBytes
196 );
197 }
198
199 return EFI_SUCCESS;
200 }
201
202 /**
203 Completes the Map() operation and releases any corresponding resources.
204
205 @param This The PPI instance pointer.
206 @param Mapping The mapping value returned from Map().
207
208 @retval EFI_SUCCESS The range was unmapped.
209 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
210 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
211 **/
212 EFI_STATUS
213 EFIAPI
214 PeiIoMmuUnmap (
215 IN EDKII_IOMMU_PPI *This,
216 IN VOID *Mapping
217 )
218 {
219 MAP_INFO *MapInfo;
220 UINTN Length;
221
222 if (Mapping == NULL) {
223 return EFI_SUCCESS;
224 }
225
226 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));
227 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
228 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
229
230 MapInfo = Mapping;
231 ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);
232 DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo->Operation, (UINTN)MapInfo->DeviceAddress, MapInfo->NumberOfBytes));
233
234 //
235 // If this is a write operation from the Bus Master's point of view,
236 // then copy the contents of the mapped buffer into the real buffer
237 // so the processor can read the contents of the real buffer.
238 //
239 if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
240 MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
241 CopyMem (
242 (VOID *) (UINTN) MapInfo->HostAddress,
243 (VOID *) (UINTN) MapInfo->DeviceAddress,
244 MapInfo->NumberOfBytes
245 );
246 }
247
248 Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
249 if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
250 mDmaBufferCurrentBottom -= Length;
251 }
252
253 return EFI_SUCCESS;
254 }
255
256 /**
257 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
258 OperationBusMasterCommonBuffer64 mapping.
259
260 @param This The PPI instance pointer.
261 @param MemoryType The type of memory to allocate, EfiBootServicesData or
262 EfiRuntimeServicesData.
263 @param Pages The number of pages to allocate.
264 @param HostAddress A pointer to store the base system memory address of the
265 allocated range.
266 @param Attributes The requested bit mask of attributes for the allocated range.
267
268 @retval EFI_SUCCESS The requested memory pages were allocated.
269 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
270 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
271 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
272 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
273
274 **/
275 EFI_STATUS
276 EFIAPI
277 PeiIoMmuAllocateBuffer (
278 IN EDKII_IOMMU_PPI *This,
279 IN EFI_MEMORY_TYPE MemoryType,
280 IN UINTN Pages,
281 IN OUT VOID **HostAddress,
282 IN UINT64 Attributes
283 )
284 {
285 UINTN Length;
286
287 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));
288 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
289 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
290
291 Length = EFI_PAGES_TO_SIZE(Pages);
292 if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
293 DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
294 ASSERT (FALSE);
295 return EFI_OUT_OF_RESOURCES;
296 }
297 *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);
298 mDmaBufferCurrentTop -= Length;
299
300 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
301 return EFI_SUCCESS;
302 }
303
304 /**
305 Frees memory that was allocated with AllocateBuffer().
306
307 @param This The PPI instance pointer.
308 @param Pages The number of pages to free.
309 @param HostAddress The base system memory address of the allocated range.
310
311 @retval EFI_SUCCESS The requested memory pages were freed.
312 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
313 was not allocated with AllocateBuffer().
314
315 **/
316 EFI_STATUS
317 EFIAPI
318 PeiIoMmuFreeBuffer (
319 IN EDKII_IOMMU_PPI *This,
320 IN UINTN Pages,
321 IN VOID *HostAddress
322 )
323 {
324 UINTN Length;
325
326 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));
327 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
328 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
329
330 Length = EFI_PAGES_TO_SIZE(Pages);
331 if ((UINTN)HostAddress == mDmaBufferCurrentTop) {
332 mDmaBufferCurrentTop += Length;
333 }
334
335 return EFI_SUCCESS;
336 }
337
338 EDKII_IOMMU_PPI mIoMmuPpi = {
339 EDKII_IOMMU_PPI_REVISION,
340 PeiIoMmuSetAttribute,
341 PeiIoMmuMap,
342 PeiIoMmuUnmap,
343 PeiIoMmuAllocateBuffer,
344 PeiIoMmuFreeBuffer,
345 };
346
347 CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
348 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
349 &gEdkiiIoMmuPpiGuid,
350 (VOID *) &mIoMmuPpi
351 };
352
353 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
354 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
355 EFI_RESOURCE_ATTRIBUTE_TESTED | \
356 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
357 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
358 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO \
359 )
360
361 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)
362
363 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)
364
365 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
366
367 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mResourceTypeShortName[] = {
368 "Mem",
369 "MMIO",
370 "I/O",
371 "FD",
372 "MM Port I/O",
373 "Reserved Mem",
374 "Reserved I/O",
375 };
376
377 /**
378 Return the short name of resource type.
379
380 @param Type resource type.
381
382 @return the short name of resource type.
383 **/
384 CHAR8 *
385 ShortNameOfResourceType (
386 IN UINT32 Type
387 )
388 {
389 if (Type < sizeof(mResourceTypeShortName) / sizeof(mResourceTypeShortName[0])) {
390 return mResourceTypeShortName[Type];
391 } else {
392 return "Unknown";
393 }
394 }
395
396 /**
397 Dump resource hob.
398
399 @param HobList the HOB list.
400 **/
401 VOID
402 DumpResourceHob (
403 IN VOID *HobList
404 )
405 {
406 EFI_PEI_HOB_POINTERS Hob;
407 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
408
409 DEBUG ((DEBUG_VERBOSE, "Resource Descriptor HOBs\n"));
410 for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
411 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
412 ResourceHob = Hob.ResourceDescriptor;
413 DEBUG ((DEBUG_VERBOSE,
414 " BA=%016lx L=%016lx Attr=%08x ",
415 ResourceHob->PhysicalStart,
416 ResourceHob->ResourceLength,
417 ResourceHob->ResourceAttribute
418 ));
419 DEBUG ((DEBUG_VERBOSE, ShortNameOfResourceType(ResourceHob->ResourceType)));
420 switch (ResourceHob->ResourceType) {
421 case EFI_RESOURCE_SYSTEM_MEMORY:
422 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) != 0) {
423 DEBUG ((DEBUG_VERBOSE, " (Persistent)"));
424 } else if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) != 0) {
425 DEBUG ((DEBUG_VERBOSE, " (MoreReliable)"));
426 } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
427 DEBUG ((DEBUG_VERBOSE, " (Tested)"));
428 } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
429 DEBUG ((DEBUG_VERBOSE, " (Init)"));
430 } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
431 DEBUG ((DEBUG_VERBOSE, " (Present)"));
432 } else {
433 DEBUG ((DEBUG_VERBOSE, " (Unknown)"));
434 }
435 break;
436 default:
437 break;
438 }
439 DEBUG ((DEBUG_VERBOSE, "\n"));
440 }
441 }
442 }
443
444 /**
445 Dump PHIT hob.
446
447 @param HobList the HOB list.
448 **/
449 VOID
450 DumpPhitHob (
451 IN VOID *HobList
452 )
453 {
454 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
455
456 PhitHob = HobList;
457 ASSERT(GET_HOB_TYPE(HobList) == EFI_HOB_TYPE_HANDOFF);
458 DEBUG ((DEBUG_VERBOSE, "PHIT HOB\n"));
459 DEBUG ((DEBUG_VERBOSE, " PhitHob - 0x%x\n", PhitHob));
460 DEBUG ((DEBUG_VERBOSE, " BootMode - 0x%x\n", PhitHob->BootMode));
461 DEBUG ((DEBUG_VERBOSE, " EfiMemoryTop - 0x%016lx\n", PhitHob->EfiMemoryTop));
462 DEBUG ((DEBUG_VERBOSE, " EfiMemoryBottom - 0x%016lx\n", PhitHob->EfiMemoryBottom));
463 DEBUG ((DEBUG_VERBOSE, " EfiFreeMemoryTop - 0x%016lx\n", PhitHob->EfiFreeMemoryTop));
464 DEBUG ((DEBUG_VERBOSE, " EfiFreeMemoryBottom - 0x%016lx\n", PhitHob->EfiFreeMemoryBottom));
465 DEBUG ((DEBUG_VERBOSE, " EfiEndOfHobList - 0x%lx\n", PhitHob->EfiEndOfHobList));
466 }
467
468 /**
469 Get the highest memory.
470
471 @return the highest memory.
472 **/
473 UINT64
474 GetTopMemory (
475 VOID
476 )
477 {
478 VOID *HobList;
479 EFI_PEI_HOB_POINTERS Hob;
480 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
481 UINT64 TopMemory;
482 UINT64 ResourceTop;
483
484 HobList = GetHobList ();
485
486 TopMemory = 0;
487 for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
488 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
489 ResourceHob = Hob.ResourceDescriptor;
490 switch (ResourceHob->ResourceType) {
491 case EFI_RESOURCE_SYSTEM_MEMORY:
492 ResourceTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
493 if (TopMemory < ResourceTop) {
494 TopMemory = ResourceTop;
495 }
496 break;
497 default:
498 break;
499 }
500 DEBUG ((DEBUG_VERBOSE, "\n"));
501 }
502 }
503 return TopMemory;
504 }
505
506 /**
507 Initialize DMA protection.
508
509 @param DmaBufferSize the DMA buffer size
510 @param DmaBufferBase the DMA buffer base
511
512 @retval EFI_SUCCESS the DMA protection is initialized.
513 @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.
514 **/
515 EFI_STATUS
516 InitDmaProtection (
517 IN UINTN DmaBufferSize,
518 OUT UINTN *DmaBufferBase
519 )
520 {
521 EFI_STATUS Status;
522 VOID *HobList;
523 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
524 UINT32 LowMemoryAlignment;
525 UINT64 HighMemoryAlignment;
526 UINTN MemoryAlignment;
527 UINTN LowBottom;
528 UINTN LowTop;
529 UINTN HighBottom;
530 UINT64 HighTop;
531
532 HobList = GetHobList ();
533 DumpPhitHob (HobList);
534 DumpResourceHob (HobList);
535
536 PhitHob = HobList;
537
538 ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
539
540 LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);
541 HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
542 if (LowMemoryAlignment < HighMemoryAlignment) {
543 MemoryAlignment = (UINTN)HighMemoryAlignment;
544 } else {
545 MemoryAlignment = LowMemoryAlignment;
546 }
547 ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));
548 *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);
549 ASSERT (*DmaBufferBase != 0);
550 if (*DmaBufferBase == 0) {
551 DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));
552 return EFI_OUT_OF_RESOURCES;
553 }
554
555 LowBottom = 0;
556 LowTop = *DmaBufferBase;
557 HighBottom = *DmaBufferBase + DmaBufferSize;
558 HighTop = GetTopMemory ();
559
560 Status = SetDmaProtectedRange (
561 mEngineMask,
562 (UINT32)LowBottom,
563 (UINT32)(LowTop - LowBottom),
564 HighBottom,
565 HighTop - HighBottom
566 );
567
568 if (EFI_ERROR(Status)) {
569 FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));
570 }
571
572 return Status;
573 }
574
575 /**
576 Dump DMAR DeviceScopeEntry.
577
578 @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
579 **/
580 VOID
581 DumpDmarDeviceScopeEntry (
582 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
583 )
584 {
585 UINTN PciPathNumber;
586 UINTN PciPathIndex;
587 EFI_ACPI_DMAR_PCI_PATH *PciPath;
588
589 if (DmarDeviceScopeEntry == NULL) {
590 return;
591 }
592
593 DEBUG ((DEBUG_INFO,
594 " *************************************************************************\n"
595 ));
596 DEBUG ((DEBUG_INFO,
597 " * DMA-Remapping Device Scope Entry Structure *\n"
598 ));
599 DEBUG ((DEBUG_INFO,
600 " *************************************************************************\n"
601 ));
602 DEBUG ((DEBUG_INFO,
603 (sizeof(UINTN) == sizeof(UINT64)) ?
604 " DMAR Device Scope Entry address ...................... 0x%016lx\n" :
605 " DMAR Device Scope Entry address ...................... 0x%08x\n",
606 DmarDeviceScopeEntry
607 ));
608 DEBUG ((DEBUG_INFO,
609 " Device Scope Entry Type ............................ 0x%02x\n",
610 DmarDeviceScopeEntry->Type
611 ));
612 switch (DmarDeviceScopeEntry->Type) {
613 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
614 DEBUG ((DEBUG_INFO,
615 " PCI Endpoint Device\n"
616 ));
617 break;
618 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
619 DEBUG ((DEBUG_INFO,
620 " PCI Sub-hierachy\n"
621 ));
622 break;
623 default:
624 break;
625 }
626 DEBUG ((DEBUG_INFO,
627 " Length ............................................. 0x%02x\n",
628 DmarDeviceScopeEntry->Length
629 ));
630 DEBUG ((DEBUG_INFO,
631 " Enumeration ID ..................................... 0x%02x\n",
632 DmarDeviceScopeEntry->EnumerationId
633 ));
634 DEBUG ((DEBUG_INFO,
635 " Starting Bus Number ................................ 0x%02x\n",
636 DmarDeviceScopeEntry->StartBusNumber
637 ));
638
639 PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
640 PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
641 for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
642 DEBUG ((DEBUG_INFO,
643 " Device ............................................. 0x%02x\n",
644 PciPath[PciPathIndex].Device
645 ));
646 DEBUG ((DEBUG_INFO,
647 " Function ........................................... 0x%02x\n",
648 PciPath[PciPathIndex].Function
649 ));
650 }
651
652 DEBUG ((DEBUG_INFO,
653 " *************************************************************************\n\n"
654 ));
655
656 return;
657 }
658
659 /**
660 Dump DMAR RMRR table.
661
662 @param[in] Rmrr DMAR RMRR table
663 **/
664 VOID
665 DumpDmarRmrr (
666 IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
667 )
668 {
669 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
670 INTN RmrrLen;
671
672 if (Rmrr == NULL) {
673 return;
674 }
675
676 DEBUG ((DEBUG_INFO,
677 " ***************************************************************************\n"
678 ));
679 DEBUG ((DEBUG_INFO,
680 " * Reserved Memory Region Reporting Structure *\n"
681 ));
682 DEBUG ((DEBUG_INFO,
683 " ***************************************************************************\n"
684 ));
685 DEBUG ((DEBUG_INFO,
686 (sizeof(UINTN) == sizeof(UINT64)) ?
687 " RMRR address ........................................... 0x%016lx\n" :
688 " RMRR address ........................................... 0x%08x\n",
689 Rmrr
690 ));
691 DEBUG ((DEBUG_INFO,
692 " Type ................................................. 0x%04x\n",
693 Rmrr->Header.Type
694 ));
695 DEBUG ((DEBUG_INFO,
696 " Length ............................................... 0x%04x\n",
697 Rmrr->Header.Length
698 ));
699 DEBUG ((DEBUG_INFO,
700 " Segment Number ....................................... 0x%04x\n",
701 Rmrr->SegmentNumber
702 ));
703 DEBUG ((DEBUG_INFO,
704 " Reserved Memory Region Base Address .................. 0x%016lx\n",
705 Rmrr->ReservedMemoryRegionBaseAddress
706 ));
707 DEBUG ((DEBUG_INFO,
708 " Reserved Memory Region Limit Address ................. 0x%016lx\n",
709 Rmrr->ReservedMemoryRegionLimitAddress
710 ));
711
712 RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
713 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);
714 while (RmrrLen > 0) {
715 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
716 RmrrLen -= DmarDeviceScopeEntry->Length;
717 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
718 }
719
720 DEBUG ((DEBUG_INFO,
721 " ***************************************************************************\n\n"
722 ));
723
724 return;
725 }
726
727 /**
728 Dump DMAR DRHD table.
729
730 @param[in] Drhd DMAR DRHD table
731 **/
732 VOID
733 DumpDmarDrhd (
734 IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
735 )
736 {
737 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
738 INTN DrhdLen;
739
740 if (Drhd == NULL) {
741 return;
742 }
743
744 DEBUG ((DEBUG_INFO,
745 " ***************************************************************************\n"
746 ));
747 DEBUG ((DEBUG_INFO,
748 " * DMA-Remapping Hardware Definition Structure *\n"
749 ));
750 DEBUG ((DEBUG_INFO,
751 " ***************************************************************************\n"
752 ));
753 DEBUG ((DEBUG_INFO,
754 (sizeof(UINTN) == sizeof(UINT64)) ?
755 " DRHD address ........................................... 0x%016lx\n" :
756 " DRHD address ........................................... 0x%08x\n",
757 Drhd
758 ));
759 DEBUG ((DEBUG_INFO,
760 " Type ................................................. 0x%04x\n",
761 Drhd->Header.Type
762 ));
763 DEBUG ((DEBUG_INFO,
764 " Length ............................................... 0x%04x\n",
765 Drhd->Header.Length
766 ));
767 DEBUG ((DEBUG_INFO,
768 " Flags ................................................ 0x%02x\n",
769 Drhd->Flags
770 ));
771 DEBUG ((DEBUG_INFO,
772 " INCLUDE_PCI_ALL .................................... 0x%02x\n",
773 Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
774 ));
775 DEBUG ((DEBUG_INFO,
776 " Segment Number ....................................... 0x%04x\n",
777 Drhd->SegmentNumber
778 ));
779 DEBUG ((DEBUG_INFO,
780 " Register Base Address ................................ 0x%016lx\n",
781 Drhd->RegisterBaseAddress
782 ));
783
784 DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
785 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
786 while (DrhdLen > 0) {
787 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
788 DrhdLen -= DmarDeviceScopeEntry->Length;
789 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
790 }
791
792 DEBUG ((DEBUG_INFO,
793 " ***************************************************************************\n\n"
794 ));
795
796 return;
797 }
798
799 /**
800 Dump DMAR ACPI table.
801
802 @param[in] Dmar DMAR ACPI table
803 **/
804 VOID
805 DumpAcpiDMAR (
806 IN EFI_ACPI_DMAR_HEADER *Dmar
807 )
808 {
809 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
810 INTN DmarLen;
811
812 if (Dmar == NULL) {
813 return;
814 }
815
816 //
817 // Dump Dmar table
818 //
819 DEBUG ((DEBUG_INFO,
820 "*****************************************************************************\n"
821 ));
822 DEBUG ((DEBUG_INFO,
823 "* DMAR Table *\n"
824 ));
825 DEBUG ((DEBUG_INFO,
826 "*****************************************************************************\n"
827 ));
828
829 DEBUG ((DEBUG_INFO,
830 (sizeof(UINTN) == sizeof(UINT64)) ?
831 "DMAR address ............................................. 0x%016lx\n" :
832 "DMAR address ............................................. 0x%08x\n",
833 Dmar
834 ));
835
836 DEBUG ((DEBUG_INFO,
837 " Table Contents:\n"
838 ));
839 DEBUG ((DEBUG_INFO,
840 " Host Address Width ................................... 0x%02x\n",
841 Dmar->HostAddressWidth
842 ));
843 DEBUG ((DEBUG_INFO,
844 " Flags ................................................ 0x%02x\n",
845 Dmar->Flags
846 ));
847 DEBUG ((DEBUG_INFO,
848 " INTR_REMAP ......................................... 0x%02x\n",
849 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
850 ));
851 DEBUG ((DEBUG_INFO,
852 " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
853 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
854 ));
855
856 DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
857 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
858 while (DmarLen > 0) {
859 switch (DmarHeader->Type) {
860 case EFI_ACPI_DMAR_TYPE_DRHD:
861 DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
862 break;
863 case EFI_ACPI_DMAR_TYPE_RMRR:
864 DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
865 break;
866 default:
867 break;
868 }
869 DmarLen -= DmarHeader->Length;
870 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
871 }
872
873 DEBUG ((DEBUG_INFO,
874 "*****************************************************************************\n\n"
875 ));
876
877 return;
878 }
879
880 /**
881 Get VTd engine number.
882
883 @return the VTd engine number.
884 **/
885 UINTN
886 GetVtdEngineNumber (
887 VOID
888 )
889 {
890 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
891 UINTN VtdIndex;
892
893 VtdIndex = 0;
894 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
895 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
896 switch (DmarHeader->Type) {
897 case EFI_ACPI_DMAR_TYPE_DRHD:
898 VtdIndex++;
899 break;
900 default:
901 break;
902 }
903 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
904 }
905 return VtdIndex ;
906 }
907
908 /**
909 Process DMAR DHRD table.
910
911 @param[in] VtdIndex The index of VTd engine.
912 @param[in] DmarDrhd The DRHD table.
913 **/
914 VOID
915 ProcessDhrd (
916 IN UINTN VtdIndex,
917 IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
918 )
919 {
920 DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
921 mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
922 }
923
924 /**
925 Parse DMAR DRHD table.
926
927 @return EFI_SUCCESS The DMAR DRHD table is parsed.
928 **/
929 EFI_STATUS
930 ParseDmarAcpiTableDrhd (
931 VOID
932 )
933 {
934 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
935 UINTN VtdUnitNumber;
936 UINTN VtdIndex;
937
938 VtdUnitNumber = GetVtdEngineNumber ();
939 if (VtdUnitNumber == 0) {
940 return EFI_UNSUPPORTED;
941 }
942
943 mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
944 if (mVTdInfo == NULL) {
945 return EFI_OUT_OF_RESOURCES;
946 }
947 mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
948 mVTdInfo->VTdEngineCount = VtdUnitNumber;
949
950 VtdIndex = 0;
951 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
952 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
953 switch (DmarHeader->Type) {
954 case EFI_ACPI_DMAR_TYPE_DRHD:
955 ASSERT (VtdIndex < VtdUnitNumber);
956 ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
957 VtdIndex++;
958
959 break;
960
961 default:
962 break;
963 }
964 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
965 }
966 ASSERT (VtdIndex == VtdUnitNumber);
967
968 //
969 // Initialize the engine mask to all.
970 //
971 mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
972
973 return EFI_SUCCESS;
974 }
975
976 /**
977 Return the VTd engine index according to the Segment and DevScopeEntry.
978
979 @param Segment The segment of the VTd engine
980 @param DevScopeEntry The DevScopeEntry of the VTd engine
981
982 @return The VTd engine index according to the Segment and DevScopeEntry.
983 @retval -1 The VTd engine is not found.
984 **/
985 UINTN
986 GetVTdEngineFromDevScopeEntry (
987 IN UINT16 Segment,
988 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
989 )
990 {
991 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
992 UINTN VtdIndex;
993 EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;
994 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;
995
996 VtdIndex = 0;
997 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
998 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
999 switch (DmarHeader->Type) {
1000 case EFI_ACPI_DMAR_TYPE_DRHD:
1001 DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
1002 if (DmarDrhd->SegmentNumber != Segment) {
1003 // Mismatch
1004 break;
1005 }
1006 if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
1007 ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
1008 // No DevScopeEntry
1009 // Do not handle PCI_ALL
1010 break;
1011 }
1012 ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
1013 while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
1014 if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
1015 (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
1016 return VtdIndex;
1017 }
1018 ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
1019 }
1020 break;
1021 default:
1022 break;
1023 }
1024 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
1025 }
1026 return (UINTN)-1;
1027 }
1028
1029 /**
1030 Process DMAR RMRR table.
1031
1032 @param[in] DmarRmrr The RMRR table.
1033 **/
1034 VOID
1035 ProcessRmrr (
1036 IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
1037 )
1038 {
1039 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
1040 UINTN VTdIndex;
1041 UINT64 RmrrMask;
1042 UINTN LowBottom;
1043 UINTN LowTop;
1044 UINTN HighBottom;
1045 UINT64 HighTop;
1046
1047 DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
1048
1049 if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
1050 (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
1051 return ;
1052 }
1053
1054 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));
1055 while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
1056 ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
1057
1058 VTdIndex = GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, DmarDevScopeEntry);
1059 if (VTdIndex != (UINTN)-1) {
1060 RmrrMask = LShiftU64 (1, VTdIndex);
1061
1062 LowBottom = 0;
1063 LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
1064 HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
1065 HighTop = GetTopMemory ();
1066
1067 SetDmaProtectedRange (
1068 RmrrMask,
1069 0,
1070 (UINT32)(LowTop - LowBottom),
1071 HighBottom,
1072 HighTop - HighBottom
1073 );
1074
1075 //
1076 // Remove the engine from the engine mask.
1077 // The assumption is that any other PEI driver does not access
1078 // the device covered by this engine.
1079 //
1080 mEngineMask = mEngineMask & (~RmrrMask);
1081 }
1082
1083 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
1084 }
1085 }
1086
1087 /**
1088 Parse DMAR DRHD table.
1089 **/
1090 VOID
1091 ParseDmarAcpiTableRmrr (
1092 VOID
1093 )
1094 {
1095 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
1096
1097 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
1098 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
1099 switch (DmarHeader->Type) {
1100 case EFI_ACPI_DMAR_TYPE_RMRR:
1101 ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
1102 break;
1103 default:
1104 break;
1105 }
1106 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
1107 }
1108 }
1109
1110 /**
1111 This function handles S3 resume task at the end of PEI
1112
1113 @param[in] PeiServices Pointer to PEI Services Table.
1114 @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
1115 caused this function to execute.
1116 @param[in] Ppi Pointer to the PPI data associated with this function.
1117
1118 @retval EFI_STATUS Always return EFI_SUCCESS
1119 **/
1120 EFI_STATUS
1121 EFIAPI
1122 S3EndOfPeiNotify(
1123 IN EFI_PEI_SERVICES **PeiServices,
1124 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
1125 IN VOID *Ppi
1126 )
1127 {
1128 UINT64 EngineMask;
1129
1130 DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));
1131
1132 if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
1133 EngineMask = LShiftU64 (1, mVTdInfo->VTdEngineCount) - 1;
1134 DisableDmaProtection (EngineMask);
1135 }
1136 return EFI_SUCCESS;
1137 }
1138
1139 EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
1140 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
1141 &gEfiEndOfPeiSignalPpiGuid,
1142 S3EndOfPeiNotify
1143 };
1144
1145 /**
1146 Initializes the Intel VTd PMR PEIM.
1147
1148 @param FileHandle Handle of the file being invoked.
1149 @param PeiServices Describes the list of possible PEI Services.
1150
1151 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
1152 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
1153
1154 **/
1155 EFI_STATUS
1156 EFIAPI
1157 IntelVTdPmrInitialize (
1158 IN EFI_PEI_FILE_HANDLE FileHandle,
1159 IN CONST EFI_PEI_SERVICES **PeiServices
1160 )
1161 {
1162 EFI_STATUS Status;
1163 EFI_BOOT_MODE BootMode;
1164
1165 if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
1166 return EFI_UNSUPPORTED;
1167 }
1168
1169 PeiServicesGetBootMode (&BootMode);
1170
1171 Status = PeiServicesLocatePpi (
1172 &gEdkiiVTdInfoPpiGuid,
1173 0,
1174 NULL,
1175 (VOID **)&mAcpiDmarTable
1176 );
1177 ASSERT_EFI_ERROR(Status);
1178
1179 DumpAcpiDMAR (mAcpiDmarTable);
1180
1181 //
1182 // Get DMAR information to local VTdInfo
1183 //
1184 Status = ParseDmarAcpiTableDrhd ();
1185 if (EFI_ERROR(Status)) {
1186 return Status;
1187 }
1188
1189 //
1190 // If there is RMRR memory, parse it here.
1191 //
1192 ParseDmarAcpiTableRmrr ();
1193
1194 if (BootMode == BOOT_ON_S3_RESUME) {
1195 mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;
1196 } else {
1197 mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
1198 }
1199 DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));
1200
1201 //
1202 // Find a pre-memory in resource hob as DMA buffer
1203 // Mark PEI memory to be DMA protected.
1204 //
1205 Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);
1206 if (EFI_ERROR(Status)) {
1207 return Status;
1208 }
1209
1210 DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));
1211
1212 mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;
1213 mDmaBufferCurrentBottom = mDmaBufferBase;
1214
1215 //
1216 // Install PPI.
1217 //
1218 Status = PeiServicesInstallPpi (&mIoMmuPpiList);
1219 ASSERT_EFI_ERROR(Status);
1220
1221 //
1222 // Register EndOfPei Notify for S3 to run FSP NotifyPhase
1223 //
1224 if (BootMode == BOOT_ON_S3_RESUME) {
1225 Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);
1226 ASSERT_EFI_ERROR (Status);
1227 }
1228
1229 return Status;
1230 }
1231