]> git.proxmox.com Git - mirror_edk2.git/blob - IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
63ba94d62b7eb27d9d09983226d64ccb0eab1753
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / IntelVTdPmrPei.c
1 /** @file
2
3 Copyright (c) 2017 - 2018, 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/MemoryDiscovered.h>
28 #include <Ppi/EndOfPeiPhase.h>
29
30 #include "IntelVTdPmrPei.h"
31
32 #define TOTAL_DMA_BUFFER_SIZE SIZE_4MB
33 #define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB
34
35 EFI_GUID mVTdInfoGuid = {
36 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }
37 };
38
39 EFI_GUID mDmaBufferInfoGuid = {
40 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }
41 };
42
43 typedef struct {
44 UINTN DmaBufferBase;
45 UINTN DmaBufferSize;
46 UINTN DmaBufferCurrentTop;
47 UINTN DmaBufferCurrentBottom;
48 } DMA_BUFFER_INFO;
49
50 #define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
51 typedef struct {
52 UINT32 Signature;
53 EDKII_IOMMU_OPERATION Operation;
54 UINTN NumberOfBytes;
55 EFI_PHYSICAL_ADDRESS HostAddress;
56 EFI_PHYSICAL_ADDRESS DeviceAddress;
57 } MAP_INFO;
58
59 /**
60
61 PEI Memory Layout:
62
63 +------------------+ <=============== PHMR.Limit (+ alignment) (1 << (HostAddressWidth + 1))
64 | Mem Resource |
65 | |
66
67 +------------------+ <------- EfiMemoryTop
68 | PEI allocated |
69 =========== +==================+ <=============== PHMR.Base
70 ^ | Commom Buf |
71 | | -------------- |
72 DMA Buffer | * DMA FREE * |
73 | | -------------- |
74 V | Read/Write Buf |
75 =========== +==================+ <=============== PLMR.Limit (+ alignment)
76 | PEI allocated |
77 | -------------- | <------- EfiFreeMemoryTop
78 | * PEI FREE * |
79 | -------------- | <------- EfiFreeMemoryBottom
80 | hob |
81 | -------------- |
82 | Stack |
83 +------------------+ <------- EfiMemoryBottom / Stack Bottom
84
85 +------------------+
86 | Mem Alloc Hob |
87 +------------------+
88
89 | |
90 | Mem Resource |
91 +------------------+ <=============== PLMR.Base (0)
92 **/
93
94 /**
95 Set IOMMU attribute for a system memory.
96
97 If the IOMMU PPI exists, the system memory cannot be used
98 for DMA by default.
99
100 When a device requests a DMA access for a system memory,
101 the device driver need use SetAttribute() to update the IOMMU
102 attribute to request DMA access (read and/or write).
103
104 @param[in] This The PPI instance pointer.
105 @param[in] Mapping The mapping value returned from Map().
106 @param[in] IoMmuAccess The IOMMU access.
107
108 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
109 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
110 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
111 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
112 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping.
113 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
114 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
115
116 **/
117 EFI_STATUS
118 EFIAPI
119 PeiIoMmuSetAttribute (
120 IN EDKII_IOMMU_PPI *This,
121 IN VOID *Mapping,
122 IN UINT64 IoMmuAccess
123 )
124 {
125 return EFI_SUCCESS;
126 }
127
128 /**
129 Provides the controller-specific addresses required to access system memory from a
130 DMA bus master.
131
132 @param This The PPI instance pointer.
133 @param Operation Indicates if the bus master is going to read or write to system memory.
134 @param HostAddress The system memory address to map to the PCI controller.
135 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
136 that were mapped.
137 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
138 access the hosts HostAddress.
139 @param Mapping A resulting value to pass to Unmap().
140
141 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
142 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
143 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
144 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
145 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
146
147 **/
148 EFI_STATUS
149 EFIAPI
150 PeiIoMmuMap (
151 IN EDKII_IOMMU_PPI *This,
152 IN EDKII_IOMMU_OPERATION Operation,
153 IN VOID *HostAddress,
154 IN OUT UINTN *NumberOfBytes,
155 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
156 OUT VOID **Mapping
157 )
158 {
159 MAP_INFO *MapInfo;
160 UINTN Length;
161 VOID *Hob;
162 DMA_BUFFER_INFO *DmaBufferInfo;
163
164 Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
165 DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
166
167 if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
168 Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
169 *DeviceAddress = (UINTN)HostAddress;
170 *Mapping = 0;
171 return EFI_SUCCESS;
172 }
173
174 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));
175 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
176 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
177
178 Length = *NumberOfBytes + sizeof(MAP_INFO);
179 if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
180 DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
181 ASSERT (FALSE);
182 return EFI_OUT_OF_RESOURCES;
183 }
184
185 *DeviceAddress = DmaBufferInfo->DmaBufferCurrentBottom;
186 DmaBufferInfo->DmaBufferCurrentBottom += Length;
187
188 MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);
189 MapInfo->Signature = MAP_INFO_SIGNATURE;
190 MapInfo->Operation = Operation;
191 MapInfo->NumberOfBytes = *NumberOfBytes;
192 MapInfo->HostAddress = (UINTN)HostAddress;
193 MapInfo->DeviceAddress = *DeviceAddress;
194 *Mapping = MapInfo;
195 DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation, (UINTN)*DeviceAddress, MapInfo));
196
197 //
198 // If this is a read operation from the Bus Master's point of view,
199 // then copy the contents of the real buffer into the mapped buffer
200 // so the Bus Master can read the contents of the real buffer.
201 //
202 if (Operation == EdkiiIoMmuOperationBusMasterRead ||
203 Operation == EdkiiIoMmuOperationBusMasterRead64) {
204 CopyMem (
205 (VOID *) (UINTN) MapInfo->DeviceAddress,
206 (VOID *) (UINTN) MapInfo->HostAddress,
207 MapInfo->NumberOfBytes
208 );
209 }
210
211 return EFI_SUCCESS;
212 }
213
214 /**
215 Completes the Map() operation and releases any corresponding resources.
216
217 @param This The PPI instance pointer.
218 @param Mapping The mapping value returned from Map().
219
220 @retval EFI_SUCCESS The range was unmapped.
221 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
222 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
223 **/
224 EFI_STATUS
225 EFIAPI
226 PeiIoMmuUnmap (
227 IN EDKII_IOMMU_PPI *This,
228 IN VOID *Mapping
229 )
230 {
231 MAP_INFO *MapInfo;
232 UINTN Length;
233 VOID *Hob;
234 DMA_BUFFER_INFO *DmaBufferInfo;
235
236 Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
237 DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
238
239 if (Mapping == NULL) {
240 return EFI_SUCCESS;
241 }
242
243 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));
244 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
245 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
246
247 MapInfo = Mapping;
248 ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);
249 DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo->Operation, (UINTN)MapInfo->DeviceAddress, MapInfo->NumberOfBytes));
250
251 //
252 // If this is a write operation from the Bus Master's point of view,
253 // then copy the contents of the mapped buffer into the real buffer
254 // so the processor can read the contents of the real buffer.
255 //
256 if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
257 MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
258 CopyMem (
259 (VOID *) (UINTN) MapInfo->HostAddress,
260 (VOID *) (UINTN) MapInfo->DeviceAddress,
261 MapInfo->NumberOfBytes
262 );
263 }
264
265 Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
266 if (DmaBufferInfo->DmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
267 DmaBufferInfo->DmaBufferCurrentBottom -= Length;
268 }
269
270 return EFI_SUCCESS;
271 }
272
273 /**
274 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
275 OperationBusMasterCommonBuffer64 mapping.
276
277 @param This The PPI instance pointer.
278 @param MemoryType The type of memory to allocate, EfiBootServicesData or
279 EfiRuntimeServicesData.
280 @param Pages The number of pages to allocate.
281 @param HostAddress A pointer to store the base system memory address of the
282 allocated range.
283 @param Attributes The requested bit mask of attributes for the allocated range.
284
285 @retval EFI_SUCCESS The requested memory pages were allocated.
286 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
287 MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.
288 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
289 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
290
291 **/
292 EFI_STATUS
293 EFIAPI
294 PeiIoMmuAllocateBuffer (
295 IN EDKII_IOMMU_PPI *This,
296 IN EFI_MEMORY_TYPE MemoryType,
297 IN UINTN Pages,
298 IN OUT VOID **HostAddress,
299 IN UINT64 Attributes
300 )
301 {
302 UINTN Length;
303 VOID *Hob;
304 DMA_BUFFER_INFO *DmaBufferInfo;
305
306 Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
307 DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
308
309 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));
310 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
311 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
312
313 Length = EFI_PAGES_TO_SIZE(Pages);
314 if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
315 DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
316 ASSERT (FALSE);
317 return EFI_OUT_OF_RESOURCES;
318 }
319 *HostAddress = (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Length);
320 DmaBufferInfo->DmaBufferCurrentTop -= Length;
321
322 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
323 return EFI_SUCCESS;
324 }
325
326 /**
327 Frees memory that was allocated with AllocateBuffer().
328
329 @param This The PPI instance pointer.
330 @param Pages The number of pages to free.
331 @param HostAddress The base system memory address of the allocated range.
332
333 @retval EFI_SUCCESS The requested memory pages were freed.
334 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
335 was not allocated with AllocateBuffer().
336
337 **/
338 EFI_STATUS
339 EFIAPI
340 PeiIoMmuFreeBuffer (
341 IN EDKII_IOMMU_PPI *This,
342 IN UINTN Pages,
343 IN VOID *HostAddress
344 )
345 {
346 UINTN Length;
347 VOID *Hob;
348 DMA_BUFFER_INFO *DmaBufferInfo;
349
350 Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
351 DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
352
353 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));
354 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
355 DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
356
357 Length = EFI_PAGES_TO_SIZE(Pages);
358 if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {
359 DmaBufferInfo->DmaBufferCurrentTop += Length;
360 }
361
362 return EFI_SUCCESS;
363 }
364
365 EDKII_IOMMU_PPI mIoMmuPpi = {
366 EDKII_IOMMU_PPI_REVISION,
367 PeiIoMmuSetAttribute,
368 PeiIoMmuMap,
369 PeiIoMmuUnmap,
370 PeiIoMmuAllocateBuffer,
371 PeiIoMmuFreeBuffer,
372 };
373
374 CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
375 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
376 &gEdkiiIoMmuPpiGuid,
377 (VOID *) &mIoMmuPpi
378 };
379
380 /**
381 Initialize DMA protection.
382
383 @param VTdInfo The VTd engine context information.
384 @param DmaBufferSize the DMA buffer size
385 @param DmaBufferBase the DMA buffer base
386
387 @retval EFI_SUCCESS the DMA protection is initialized.
388 @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.
389 **/
390 EFI_STATUS
391 InitDmaProtection (
392 IN VTD_INFO *VTdInfo,
393 IN UINTN DmaBufferSize,
394 OUT UINTN *DmaBufferBase
395 )
396 {
397 EFI_STATUS Status;
398 UINT32 LowMemoryAlignment;
399 UINT64 HighMemoryAlignment;
400 UINTN MemoryAlignment;
401 UINTN LowBottom;
402 UINTN LowTop;
403 UINTN HighBottom;
404 UINT64 HighTop;
405
406 LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
407 HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
408 if (LowMemoryAlignment < HighMemoryAlignment) {
409 MemoryAlignment = (UINTN)HighMemoryAlignment;
410 } else {
411 MemoryAlignment = LowMemoryAlignment;
412 }
413 ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));
414 *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);
415 ASSERT (*DmaBufferBase != 0);
416 if (*DmaBufferBase == 0) {
417 DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));
418 return EFI_OUT_OF_RESOURCES;
419 }
420
421 LowBottom = 0;
422 LowTop = *DmaBufferBase;
423 HighBottom = *DmaBufferBase + DmaBufferSize;
424 HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);
425
426 Status = SetDmaProtectedRange (
427 VTdInfo,
428 VTdInfo->EngineMask,
429 (UINT32)LowBottom,
430 (UINT32)(LowTop - LowBottom),
431 HighBottom,
432 HighTop - HighBottom
433 );
434
435 if (EFI_ERROR(Status)) {
436 FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));
437 }
438
439 return Status;
440 }
441
442 /**
443 Initializes the Intel VTd Info.
444
445 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
446 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
447
448 **/
449 EFI_STATUS
450 InitVTdInfo (
451 VOID
452 )
453 {
454 EFI_STATUS Status;
455 EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
456 VOID *Hob;
457
458 Status = PeiServicesLocatePpi (
459 &gEdkiiVTdInfoPpiGuid,
460 0,
461 NULL,
462 (VOID **)&AcpiDmarTable
463 );
464 ASSERT_EFI_ERROR(Status);
465
466 DumpAcpiDMAR (AcpiDmarTable);
467
468 //
469 // Clear old VTdInfo Hob.
470 //
471 Hob = GetFirstGuidHob (&mVTdInfoGuid);
472 if (Hob != NULL) {
473 ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID));
474 }
475
476 //
477 // Get DMAR information to local VTdInfo
478 //
479 Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);
480 if (EFI_ERROR(Status)) {
481 return Status;
482 }
483
484 //
485 // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.
486 //
487
488 return EFI_SUCCESS;
489 }
490
491 /**
492 Initializes the Intel VTd PMR for all memory.
493
494 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
495 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
496
497 **/
498 EFI_STATUS
499 InitVTdPmrForAll (
500 VOID
501 )
502 {
503 EFI_STATUS Status;
504 VOID *Hob;
505 VTD_INFO *VTdInfo;
506 UINTN LowBottom;
507 UINTN LowTop;
508 UINTN HighBottom;
509 UINT64 HighTop;
510
511 Hob = GetFirstGuidHob (&mVTdInfoGuid);
512 VTdInfo = GET_GUID_HOB_DATA(Hob);
513
514 LowBottom = 0;
515 LowTop = 0;
516 HighBottom = 0;
517 HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);
518
519 Status = SetDmaProtectedRange (
520 VTdInfo,
521 VTdInfo->EngineMask,
522 (UINT32)LowBottom,
523 (UINT32)(LowTop - LowBottom),
524 HighBottom,
525 HighTop - HighBottom
526 );
527
528 return Status;
529 }
530
531 /**
532 Initializes the Intel VTd PMR for DMA buffer.
533
534 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
535 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
536
537 **/
538 EFI_STATUS
539 InitVTdPmrForDma (
540 VOID
541 )
542 {
543 EFI_STATUS Status;
544 VOID *Hob;
545 VTD_INFO *VTdInfo;
546 DMA_BUFFER_INFO *DmaBufferInfo;
547
548 Hob = GetFirstGuidHob (&mVTdInfoGuid);
549 VTdInfo = GET_GUID_HOB_DATA(Hob);
550
551 //
552 // If there is RMRR memory, parse it here.
553 //
554 ParseDmarAcpiTableRmrr (VTdInfo);
555
556 Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
557 DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
558
559 DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));
560 //
561 // Find a pre-memory in resource hob as DMA buffer
562 // Mark PEI memory to be DMA protected.
563 //
564 Status = InitDmaProtection (VTdInfo, DmaBufferInfo->DmaBufferSize, &DmaBufferInfo->DmaBufferBase);
565 if (EFI_ERROR(Status)) {
566 return Status;
567 }
568
569 DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));
570
571 DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
572 DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;
573
574 //
575 // Install PPI.
576 //
577 Status = PeiServicesInstallPpi (&mIoMmuPpiList);
578 ASSERT_EFI_ERROR(Status);
579
580 return Status;
581 }
582
583 /**
584 This function handles S3 resume task at the end of PEI
585
586 @param[in] PeiServices Pointer to PEI Services Table.
587 @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
588 caused this function to execute.
589 @param[in] Ppi Pointer to the PPI data associated with this function.
590
591 @retval EFI_STATUS Always return EFI_SUCCESS
592 **/
593 EFI_STATUS
594 EFIAPI
595 S3EndOfPeiNotify(
596 IN EFI_PEI_SERVICES **PeiServices,
597 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
598 IN VOID *Ppi
599 )
600 {
601 VOID *Hob;
602 VTD_INFO *VTdInfo;
603 UINT64 EngineMask;
604
605 DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));
606
607 if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
608 Hob = GetFirstGuidHob (&mVTdInfoGuid);
609 if (Hob == NULL) {
610 return EFI_SUCCESS;
611 }
612 VTdInfo = GET_GUID_HOB_DATA(Hob);
613
614 EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
615 DisableDmaProtection (VTdInfo, EngineMask);
616 }
617 return EFI_SUCCESS;
618 }
619
620 EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
621 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
622 &gEfiEndOfPeiSignalPpiGuid,
623 S3EndOfPeiNotify
624 };
625
626 /**
627 This function handles VTd engine setup
628
629 @param[in] PeiServices Pointer to PEI Services Table.
630 @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
631 caused this function to execute.
632 @param[in] Ppi Pointer to the PPI data associated with this function.
633
634 @retval EFI_STATUS Always return EFI_SUCCESS
635 **/
636 EFI_STATUS
637 EFIAPI
638 VTdInfoNotify (
639 IN EFI_PEI_SERVICES **PeiServices,
640 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
641 IN VOID *Ppi
642 )
643 {
644 EFI_STATUS Status;
645 VOID *MemoryDiscovered;
646 UINT64 EnabledEngineMask;
647 VOID *Hob;
648 VTD_INFO *VTdInfo;
649 BOOLEAN MemoryInitialized;
650
651 DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));
652
653 //
654 // Check if memory is initialized.
655 //
656 MemoryInitialized = FALSE;
657 Status = PeiServicesLocatePpi (
658 &gEfiPeiMemoryDiscoveredPpiGuid,
659 0,
660 NULL,
661 &MemoryDiscovered
662 );
663 if (!EFI_ERROR(Status)) {
664 MemoryInitialized = TRUE;
665 }
666
667 DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));
668
669 if (!MemoryInitialized) {
670 //
671 // If the memory is not initialized,
672 // Protect all system memory
673 //
674 InitVTdInfo ();
675 InitVTdPmrForAll ();
676 } else {
677 //
678 // If the memory is initialized,
679 // Allocate DMA buffer and protect rest system memory
680 //
681
682 //
683 // NOTE: We need reinit VTdInfo because previous information might be overriden.
684 //
685 InitVTdInfo ();
686
687 Hob = GetFirstGuidHob (&mVTdInfoGuid);
688 VTdInfo = GET_GUID_HOB_DATA(Hob);
689
690 //
691 // NOTE: We need check if PMR is enabled or not.
692 //
693 EnabledEngineMask = GetDmaProtectionEnabledEngineMask (VTdInfo, VTdInfo->EngineMask);
694 if (EnabledEngineMask != 0) {
695 EnableVTdTranslationProtection (VTdInfo, EnabledEngineMask);
696 DisableDmaProtection (VTdInfo, EnabledEngineMask);
697 }
698 InitVTdPmrForDma ();
699 if (EnabledEngineMask != 0) {
700 DisableVTdTranslationProtection (VTdInfo, EnabledEngineMask);
701 }
702
703 }
704
705 return EFI_SUCCESS;
706 }
707
708 EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc = {
709 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
710 &gEdkiiVTdInfoPpiGuid,
711 VTdInfoNotify
712 };
713
714 /**
715 Initializes the Intel VTd PMR PEIM.
716
717 @param FileHandle Handle of the file being invoked.
718 @param PeiServices Describes the list of possible PEI Services.
719
720 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
721 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
722
723 **/
724 EFI_STATUS
725 EFIAPI
726 IntelVTdPmrInitialize (
727 IN EFI_PEI_FILE_HANDLE FileHandle,
728 IN CONST EFI_PEI_SERVICES **PeiServices
729 )
730 {
731 EFI_STATUS Status;
732 EFI_BOOT_MODE BootMode;
733 DMA_BUFFER_INFO *DmaBufferInfo;
734
735 DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n"));
736
737 if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
738 return EFI_UNSUPPORTED;
739 }
740
741 DmaBufferInfo = BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_INFO));
742 ASSERT(DmaBufferInfo != NULL);
743 if (DmaBufferInfo == NULL) {
744 return EFI_OUT_OF_RESOURCES;
745 }
746 ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO));
747
748 PeiServicesGetBootMode (&BootMode);
749
750 if (BootMode == BOOT_ON_S3_RESUME) {
751 DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;
752 } else {
753 DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
754 }
755
756 Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);
757 ASSERT_EFI_ERROR (Status);
758
759 //
760 // Register EndOfPei Notify for S3
761 //
762 if (BootMode == BOOT_ON_S3_RESUME) {
763 Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);
764 ASSERT_EFI_ERROR (Status);
765 }
766
767 return EFI_SUCCESS;
768 }
769