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