]> git.proxmox.com Git - mirror_edk2.git/blob - IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
IntelSiliconPkg/PlatformVTdSampleDxe: Move to feature dir.
[mirror_edk2.git] / IntelSiliconPkg / 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 EDKII_VTD_INFO_PPI *mVTdInfoPpi;
33 UINTN mDmaBufferBase;
34 UINTN mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
35 UINTN mDmaBufferCurrentTop;
36 UINTN mDmaBufferCurrentBottom;
37
38 #define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
39 typedef struct {
40 UINT32 Signature;
41 EDKII_IOMMU_OPERATION Operation;
42 UINTN NumberOfBytes;
43 EFI_PHYSICAL_ADDRESS HostAddress;
44 EFI_PHYSICAL_ADDRESS DeviceAddress;
45 } MAP_INFO;
46
47 /**
48
49 PEI Memory Layout:
50
51 +------------------+ <------- EfiMemoryTop
52 | PEI allocated |
53 =========== +==================+
54 ^ | Commom Buf |
55 | | -------------- |
56 DMA Buffer | * DMA FREE * |
57 | | -------------- |
58 V | Read/Write Buf |
59 =========== +==================+
60 | PEI allocated |
61 | -------------- | <------- EfiFreeMemoryTop
62 | * PEI FREE * |
63 | -------------- | <------- EfiFreeMemoryBottom
64 | hob |
65 | -------------- |
66 | Stack |
67 +------------------+ <------- EfiMemoryBottom / Stack Bottom
68
69 +------------------+
70 | Mem Alloc Hob |
71 +------------------+
72
73 **/
74
75
76 /**
77 Set IOMMU attribute for a system memory.
78
79 If the IOMMU PPI exists, the system memory cannot be used
80 for DMA by default.
81
82 When a device requests a DMA access for a system memory,
83 the device driver need use SetAttribute() to update the IOMMU
84 attribute to request DMA access (read and/or write).
85
86 @param[in] This The PPI instance pointer.
87 @param[in] Mapping The mapping value returned from Map().
88 @param[in] IoMmuAccess The IOMMU access.
89
90 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
91 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
92 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
93 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
94 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by Mapping.
95 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
96 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
97
98 **/
99 EFI_STATUS
100 EFIAPI
101 PeiIoMmuSetAttribute (
102 IN EDKII_IOMMU_PPI *This,
103 IN VOID *Mapping,
104 IN UINT64 IoMmuAccess
105 )
106 {
107 return EFI_SUCCESS;
108 }
109
110 /**
111 Provides the controller-specific addresses required to access system memory from a
112 DMA bus master.
113
114 @param This The PPI instance pointer.
115 @param Operation Indicates if the bus master is going to read or write to system memory.
116 @param HostAddress The system memory address to map to the PCI controller.
117 @param NumberOfBytes On input the number of bytes to map. On output the number of bytes
118 that were mapped.
119 @param DeviceAddress The resulting map address for the bus master PCI controller to use to
120 access the hosts HostAddress.
121 @param Mapping A resulting value to pass to Unmap().
122
123 @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
124 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
125 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
126 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
127 @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
128
129 **/
130 EFI_STATUS
131 EFIAPI
132 PeiIoMmuMap (
133 IN EDKII_IOMMU_PPI *This,
134 IN EDKII_IOMMU_OPERATION Operation,
135 IN VOID *HostAddress,
136 IN OUT UINTN *NumberOfBytes,
137 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
138 OUT VOID **Mapping
139 )
140 {
141 MAP_INFO *MapInfo;
142 UINTN Length;
143
144 if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
145 Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
146 *DeviceAddress = (UINTN)HostAddress;
147 *Mapping = 0;
148 return EFI_SUCCESS;
149 }
150
151 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));
152 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
153 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
154
155 Length = *NumberOfBytes + sizeof(MAP_INFO);
156 if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
157 DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
158 ASSERT (FALSE);
159 return EFI_OUT_OF_RESOURCES;
160 }
161
162 *DeviceAddress = mDmaBufferCurrentBottom;
163 mDmaBufferCurrentBottom += Length;
164
165 MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);
166 MapInfo->Signature = MAP_INFO_SIGNATURE;
167 MapInfo->Operation = Operation;
168 MapInfo->NumberOfBytes = *NumberOfBytes;
169 MapInfo->HostAddress = (UINTN)HostAddress;
170 MapInfo->DeviceAddress = *DeviceAddress;
171 *Mapping = MapInfo;
172 DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation, (UINTN)*DeviceAddress, MapInfo));
173
174 //
175 // If this is a read operation from the Bus Master's point of view,
176 // then copy the contents of the real buffer into the mapped buffer
177 // so the Bus Master can read the contents of the real buffer.
178 //
179 if (Operation == EdkiiIoMmuOperationBusMasterRead ||
180 Operation == EdkiiIoMmuOperationBusMasterRead64) {
181 CopyMem (
182 (VOID *) (UINTN) MapInfo->DeviceAddress,
183 (VOID *) (UINTN) MapInfo->HostAddress,
184 MapInfo->NumberOfBytes
185 );
186 }
187
188 return EFI_SUCCESS;
189 }
190
191 /**
192 Completes the Map() operation and releases any corresponding resources.
193
194 @param This The PPI instance pointer.
195 @param Mapping The mapping value returned from Map().
196
197 @retval EFI_SUCCESS The range was unmapped.
198 @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
199 @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
200 **/
201 EFI_STATUS
202 EFIAPI
203 PeiIoMmuUnmap (
204 IN EDKII_IOMMU_PPI *This,
205 IN VOID *Mapping
206 )
207 {
208 MAP_INFO *MapInfo;
209 UINTN Length;
210
211 if (Mapping == NULL) {
212 return EFI_SUCCESS;
213 }
214
215 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));
216 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
217 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
218
219 MapInfo = Mapping;
220 ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);
221 DEBUG ((DEBUG_VERBOSE, " Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo->Operation, (UINTN)MapInfo->DeviceAddress, MapInfo->NumberOfBytes));
222
223 //
224 // If this is a write operation from the Bus Master's point of view,
225 // then copy the contents of the mapped buffer into the real buffer
226 // so the processor can read the contents of the real buffer.
227 //
228 if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
229 MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
230 CopyMem (
231 (VOID *) (UINTN) MapInfo->HostAddress,
232 (VOID *) (UINTN) MapInfo->DeviceAddress,
233 MapInfo->NumberOfBytes
234 );
235 }
236
237 Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
238 if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
239 mDmaBufferCurrentBottom -= Length;
240 }
241
242 return EFI_SUCCESS;
243 }
244
245 /**
246 Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
247 OperationBusMasterCommonBuffer64 mapping.
248
249 @param This The PPI instance pointer.
250 @param MemoryType The type of memory to allocate, EfiBootServicesData or
251 EfiRuntimeServicesData.
252 @param Pages The number of pages to allocate.
253 @param HostAddress A pointer to store the base system memory address of the
254 allocated range.
255 @param Attributes The requested bit mask of attributes for the allocated range.
256
257 @retval EFI_SUCCESS The requested memory pages were allocated.
258 @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
259 MEMORY_WRITE_COMBINE and MEMORY_CACHED.
260 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
261 @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
262
263 **/
264 EFI_STATUS
265 EFIAPI
266 PeiIoMmuAllocateBuffer (
267 IN EDKII_IOMMU_PPI *This,
268 IN EFI_MEMORY_TYPE MemoryType,
269 IN UINTN Pages,
270 IN OUT VOID **HostAddress,
271 IN UINT64 Attributes
272 )
273 {
274 UINTN Length;
275
276 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));
277 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
278 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
279
280 Length = EFI_PAGES_TO_SIZE(Pages);
281 if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
282 DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
283 ASSERT (FALSE);
284 return EFI_OUT_OF_RESOURCES;
285 }
286 *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);
287 mDmaBufferCurrentTop -= Length;
288
289 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
290 return EFI_SUCCESS;
291 }
292
293 /**
294 Frees memory that was allocated with AllocateBuffer().
295
296 @param This The PPI instance pointer.
297 @param Pages The number of pages to free.
298 @param HostAddress The base system memory address of the allocated range.
299
300 @retval EFI_SUCCESS The requested memory pages were freed.
301 @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
302 was not allocated with AllocateBuffer().
303
304 **/
305 EFI_STATUS
306 EFIAPI
307 PeiIoMmuFreeBuffer (
308 IN EDKII_IOMMU_PPI *This,
309 IN UINTN Pages,
310 IN VOID *HostAddress
311 )
312 {
313 UINTN Length;
314
315 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));
316 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
317 DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
318
319 Length = EFI_PAGES_TO_SIZE(Pages);
320 if ((UINTN)HostAddress == mDmaBufferCurrentTop) {
321 mDmaBufferCurrentTop += Length;
322 }
323
324 return EFI_SUCCESS;
325 }
326
327 EDKII_IOMMU_PPI mIoMmuPpi = {
328 EDKII_IOMMU_PPI_REVISION,
329 PeiIoMmuSetAttribute,
330 PeiIoMmuMap,
331 PeiIoMmuUnmap,
332 PeiIoMmuAllocateBuffer,
333 PeiIoMmuFreeBuffer,
334 };
335
336 CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
337 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
338 &gEdkiiIoMmuPpiGuid,
339 (VOID *) &mIoMmuPpi
340 };
341
342 #define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
343 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
344 EFI_RESOURCE_ATTRIBUTE_TESTED | \
345 EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
346 EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
347 EFI_RESOURCE_ATTRIBUTE_64_BIT_IO \
348 )
349
350 #define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)
351
352 #define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)
353
354 #define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
355
356 GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mResourceTypeShortName[] = {
357 "Mem",
358 "MMIO",
359 "I/O",
360 "FD",
361 "MM Port I/O",
362 "Reserved Mem",
363 "Reserved I/O",
364 };
365
366 /**
367 Return the short name of resource type.
368
369 @param Type resource type.
370
371 @return the short name of resource type.
372 **/
373 CHAR8 *
374 ShortNameOfResourceType (
375 IN UINT32 Type
376 )
377 {
378 if (Type < sizeof(mResourceTypeShortName) / sizeof(mResourceTypeShortName[0])) {
379 return mResourceTypeShortName[Type];
380 } else {
381 return "Unknown";
382 }
383 }
384
385 /**
386 Dump resource hob.
387
388 @param HobList the HOB list.
389 **/
390 VOID
391 DumpResourceHob (
392 IN VOID *HobList
393 )
394 {
395 EFI_PEI_HOB_POINTERS Hob;
396 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
397
398 DEBUG ((DEBUG_VERBOSE, "Resource Descriptor HOBs\n"));
399 for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
400 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
401 ResourceHob = Hob.ResourceDescriptor;
402 DEBUG ((DEBUG_VERBOSE,
403 " BA=%016lx L=%016lx Attr=%08x ",
404 ResourceHob->PhysicalStart,
405 ResourceHob->ResourceLength,
406 ResourceHob->ResourceAttribute
407 ));
408 DEBUG ((DEBUG_VERBOSE, ShortNameOfResourceType(ResourceHob->ResourceType)));
409 switch (ResourceHob->ResourceType) {
410 case EFI_RESOURCE_SYSTEM_MEMORY:
411 if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) != 0) {
412 DEBUG ((DEBUG_VERBOSE, " (Persistent)"));
413 } else if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) != 0) {
414 DEBUG ((DEBUG_VERBOSE, " (MoreReliable)"));
415 } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
416 DEBUG ((DEBUG_VERBOSE, " (Tested)"));
417 } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
418 DEBUG ((DEBUG_VERBOSE, " (Init)"));
419 } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
420 DEBUG ((DEBUG_VERBOSE, " (Present)"));
421 } else {
422 DEBUG ((DEBUG_VERBOSE, " (Unknown)"));
423 }
424 break;
425 default:
426 break;
427 }
428 DEBUG ((DEBUG_VERBOSE, "\n"));
429 }
430 }
431 }
432
433 /**
434 Dump PHIT hob.
435
436 @param HobList the HOB list.
437 **/
438 VOID
439 DumpPhitHob (
440 IN VOID *HobList
441 )
442 {
443 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
444
445 PhitHob = HobList;
446 ASSERT(GET_HOB_TYPE(HobList) == EFI_HOB_TYPE_HANDOFF);
447 DEBUG ((DEBUG_VERBOSE, "PHIT HOB\n"));
448 DEBUG ((DEBUG_VERBOSE, " PhitHob - 0x%x\n", PhitHob));
449 DEBUG ((DEBUG_VERBOSE, " BootMode - 0x%x\n", PhitHob->BootMode));
450 DEBUG ((DEBUG_VERBOSE, " EfiMemoryTop - 0x%016lx\n", PhitHob->EfiMemoryTop));
451 DEBUG ((DEBUG_VERBOSE, " EfiMemoryBottom - 0x%016lx\n", PhitHob->EfiMemoryBottom));
452 DEBUG ((DEBUG_VERBOSE, " EfiFreeMemoryTop - 0x%016lx\n", PhitHob->EfiFreeMemoryTop));
453 DEBUG ((DEBUG_VERBOSE, " EfiFreeMemoryBottom - 0x%016lx\n", PhitHob->EfiFreeMemoryBottom));
454 DEBUG ((DEBUG_VERBOSE, " EfiEndOfHobList - 0x%lx\n", PhitHob->EfiEndOfHobList));
455 }
456
457 /**
458 Get the highest memory.
459
460 @param HobList the HOB list.
461
462 @return the highest memory.
463 **/
464 UINT64
465 GetTopMemory (
466 IN VOID *HobList
467 )
468 {
469 EFI_PEI_HOB_POINTERS Hob;
470 EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
471 UINT64 TopMemory;
472 UINT64 ResourceTop;
473
474 TopMemory = 0;
475 for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
476 if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
477 ResourceHob = Hob.ResourceDescriptor;
478 switch (ResourceHob->ResourceType) {
479 case EFI_RESOURCE_SYSTEM_MEMORY:
480 ResourceTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
481 if (TopMemory < ResourceTop) {
482 TopMemory = ResourceTop;
483 }
484 break;
485 default:
486 break;
487 }
488 DEBUG ((DEBUG_VERBOSE, "\n"));
489 }
490 }
491 return TopMemory;
492 }
493
494 /**
495 Initialize DMA protection.
496
497 @param DmaBufferSize the DMA buffer size
498 @param DmaBufferBase the DMA buffer base
499
500 @retval EFI_SUCCESS the DMA protection is initialized.
501 @retval EFI_OUT_OF_RESOURCES no enough resource to initialize DMA protection.
502 **/
503 EFI_STATUS
504 InitDmaProtection (
505 IN UINTN DmaBufferSize,
506 OUT UINTN *DmaBufferBase
507 )
508 {
509 EFI_STATUS Status;
510 VOID *HobList;
511 EFI_HOB_HANDOFF_INFO_TABLE *PhitHob;
512 UINT32 LowMemoryAlignment;
513 UINT64 HighMemoryAlignment;
514 UINTN MemoryAlignment;
515 UINTN LowBottom;
516 UINTN LowTop;
517 UINTN HighBottom;
518 UINT64 HighTop;
519
520 HobList = GetHobList ();
521 DumpPhitHob (HobList);
522 DumpResourceHob (HobList);
523
524 PhitHob = HobList;
525
526 ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
527
528 LowMemoryAlignment = GetLowMemoryAlignment ();
529 HighMemoryAlignment = GetHighMemoryAlignment ();
530 if (LowMemoryAlignment < HighMemoryAlignment) {
531 MemoryAlignment = (UINTN)HighMemoryAlignment;
532 } else {
533 MemoryAlignment = LowMemoryAlignment;
534 }
535 ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));
536 *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);
537 if (*DmaBufferBase == 0) {
538 DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));
539 return EFI_OUT_OF_RESOURCES;
540 }
541
542 LowBottom = 0;
543 LowTop = *DmaBufferBase;
544 HighBottom = *DmaBufferBase + DmaBufferSize;
545 HighTop = GetTopMemory (HobList);
546
547 Status = SetDmaProtectedRange (
548 (UINT32)LowBottom,
549 (UINT32)(LowTop - LowBottom),
550 HighBottom,
551 HighTop - HighBottom
552 );
553
554 if (EFI_ERROR(Status)) {
555 FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));
556 }
557
558 return Status;
559 }
560
561 /**
562 Initializes the Intel VTd PMR PEIM.
563
564 @param FileHandle Handle of the file being invoked.
565 @param PeiServices Describes the list of possible PEI Services.
566
567 @retval EFI_SUCCESS Usb bot driver is successfully initialized.
568 @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
569
570 **/
571 EFI_STATUS
572 EFIAPI
573 IntelVTdPmrInitialize (
574 IN EFI_PEI_FILE_HANDLE FileHandle,
575 IN CONST EFI_PEI_SERVICES **PeiServices
576 )
577 {
578 EFI_STATUS Status;
579
580 if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
581 return EFI_UNSUPPORTED;
582 }
583
584 Status = PeiServicesLocatePpi (
585 &gEdkiiVTdInfoPpiGuid,
586 0,
587 NULL,
588 (VOID **)&mVTdInfoPpi
589 );
590 ASSERT_EFI_ERROR(Status);
591
592 //
593 // Find a pre-memory in resource hob as DMA buffer
594 // Mark PEI memory to be DMA protected.
595 //
596 Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);
597 if (EFI_ERROR(Status)) {
598 return Status;
599 }
600
601 DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));
602 DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));
603
604 mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;
605 mDmaBufferCurrentBottom = mDmaBufferBase;
606
607 //
608 // Install PPI.
609 //
610 Status = PeiServicesInstallPpi (&mIoMmuPpiList);
611 ASSERT_EFI_ERROR(Status);
612
613 return Status;
614 }
615