IntelSiliconPkg/Vtd: Add DMA_CTRL_PLATFORM_OPT_IN_FLAG dump
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / DmarTable.c
CommitLineData
a1e7cd0b
JY
1/** @file\r
2\r
b2725f57 3 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
a1e7cd0b
JY
4 This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php.\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12**/\r
13\r
14#include <Uefi.h>\r
15#include <PiPei.h>\r
16#include <Library/BaseLib.h>\r
17#include <Library/BaseMemoryLib.h>\r
18#include <Library/DebugLib.h>\r
19#include <Library/HobLib.h>\r
20#include <IndustryStandard/Vtd.h>\r
21#include <Ppi/VtdInfo.h>\r
22\r
23#include "IntelVTdPmrPei.h"\r
24\r
25/**\r
26 Dump DMAR DeviceScopeEntry.\r
27\r
28 @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry\r
29**/\r
30VOID\r
31DumpDmarDeviceScopeEntry (\r
32 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry\r
33 )\r
34{\r
35 UINTN PciPathNumber;\r
36 UINTN PciPathIndex;\r
37 EFI_ACPI_DMAR_PCI_PATH *PciPath;\r
38\r
39 if (DmarDeviceScopeEntry == NULL) {\r
40 return;\r
41 }\r
42\r
43 DEBUG ((DEBUG_INFO,\r
44 " *************************************************************************\n"\r
45 ));\r
46 DEBUG ((DEBUG_INFO,\r
47 " * DMA-Remapping Device Scope Entry Structure *\n"\r
48 ));\r
49 DEBUG ((DEBUG_INFO,\r
50 " *************************************************************************\n"\r
51 ));\r
52 DEBUG ((DEBUG_INFO,\r
53 (sizeof(UINTN) == sizeof(UINT64)) ?\r
54 " DMAR Device Scope Entry address ...................... 0x%016lx\n" :\r
55 " DMAR Device Scope Entry address ...................... 0x%08x\n",\r
56 DmarDeviceScopeEntry\r
57 ));\r
58 DEBUG ((DEBUG_INFO,\r
59 " Device Scope Entry Type ............................ 0x%02x\n",\r
60 DmarDeviceScopeEntry->Type\r
61 ));\r
62 switch (DmarDeviceScopeEntry->Type) {\r
63 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
64 DEBUG ((DEBUG_INFO,\r
65 " PCI Endpoint Device\n"\r
66 ));\r
67 break;\r
68 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
69 DEBUG ((DEBUG_INFO,\r
70 " PCI Sub-hierachy\n"\r
71 ));\r
72 break;\r
73 default:\r
74 break;\r
75 }\r
76 DEBUG ((DEBUG_INFO,\r
77 " Length ............................................. 0x%02x\n",\r
78 DmarDeviceScopeEntry->Length\r
79 ));\r
80 DEBUG ((DEBUG_INFO,\r
81 " Enumeration ID ..................................... 0x%02x\n",\r
82 DmarDeviceScopeEntry->EnumerationId\r
83 ));\r
84 DEBUG ((DEBUG_INFO,\r
85 " Starting Bus Number ................................ 0x%02x\n",\r
86 DmarDeviceScopeEntry->StartBusNumber\r
87 ));\r
88\r
89 PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);\r
90 PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);\r
91 for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {\r
92 DEBUG ((DEBUG_INFO,\r
93 " Device ............................................. 0x%02x\n",\r
94 PciPath[PciPathIndex].Device\r
95 ));\r
96 DEBUG ((DEBUG_INFO,\r
97 " Function ........................................... 0x%02x\n",\r
98 PciPath[PciPathIndex].Function\r
99 ));\r
100 }\r
101\r
102 DEBUG ((DEBUG_INFO,\r
103 " *************************************************************************\n\n"\r
104 ));\r
105\r
106 return;\r
107}\r
108\r
109/**\r
110 Dump DMAR RMRR table.\r
111\r
112 @param[in] Rmrr DMAR RMRR table\r
113**/\r
114VOID\r
115DumpDmarRmrr (\r
116 IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr\r
117 )\r
118{\r
119 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
120 INTN RmrrLen;\r
121\r
122 if (Rmrr == NULL) {\r
123 return;\r
124 }\r
125\r
126 DEBUG ((DEBUG_INFO,\r
127 " ***************************************************************************\n"\r
128 ));\r
129 DEBUG ((DEBUG_INFO,\r
130 " * Reserved Memory Region Reporting Structure *\n"\r
131 ));\r
132 DEBUG ((DEBUG_INFO,\r
133 " ***************************************************************************\n"\r
134 ));\r
135 DEBUG ((DEBUG_INFO,\r
136 (sizeof(UINTN) == sizeof(UINT64)) ?\r
137 " RMRR address ........................................... 0x%016lx\n" :\r
138 " RMRR address ........................................... 0x%08x\n",\r
139 Rmrr\r
140 ));\r
141 DEBUG ((DEBUG_INFO,\r
142 " Type ................................................. 0x%04x\n",\r
143 Rmrr->Header.Type\r
144 ));\r
145 DEBUG ((DEBUG_INFO,\r
146 " Length ............................................... 0x%04x\n",\r
147 Rmrr->Header.Length\r
148 ));\r
149 DEBUG ((DEBUG_INFO,\r
150 " Segment Number ....................................... 0x%04x\n",\r
151 Rmrr->SegmentNumber\r
152 ));\r
153 DEBUG ((DEBUG_INFO,\r
154 " Reserved Memory Region Base Address .................. 0x%016lx\n",\r
155 Rmrr->ReservedMemoryRegionBaseAddress\r
156 ));\r
157 DEBUG ((DEBUG_INFO,\r
158 " Reserved Memory Region Limit Address ................. 0x%016lx\n",\r
159 Rmrr->ReservedMemoryRegionLimitAddress\r
160 ));\r
161\r
162 RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);\r
163 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);\r
164 while (RmrrLen > 0) {\r
165 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
166 RmrrLen -= DmarDeviceScopeEntry->Length;\r
167 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
168 }\r
169\r
170 DEBUG ((DEBUG_INFO,\r
171 " ***************************************************************************\n\n"\r
172 ));\r
173\r
174 return;\r
175}\r
176\r
177/**\r
178 Dump DMAR DRHD table.\r
179\r
180 @param[in] Drhd DMAR DRHD table\r
181**/\r
182VOID\r
183DumpDmarDrhd (\r
184 IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd\r
185 )\r
186{\r
187 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
188 INTN DrhdLen;\r
189\r
190 if (Drhd == NULL) {\r
191 return;\r
192 }\r
193\r
194 DEBUG ((DEBUG_INFO,\r
195 " ***************************************************************************\n"\r
196 ));\r
197 DEBUG ((DEBUG_INFO,\r
198 " * DMA-Remapping Hardware Definition Structure *\n"\r
199 ));\r
200 DEBUG ((DEBUG_INFO,\r
201 " ***************************************************************************\n"\r
202 ));\r
203 DEBUG ((DEBUG_INFO,\r
204 (sizeof(UINTN) == sizeof(UINT64)) ?\r
205 " DRHD address ........................................... 0x%016lx\n" :\r
206 " DRHD address ........................................... 0x%08x\n",\r
207 Drhd\r
208 ));\r
209 DEBUG ((DEBUG_INFO,\r
210 " Type ................................................. 0x%04x\n",\r
211 Drhd->Header.Type\r
212 ));\r
213 DEBUG ((DEBUG_INFO,\r
214 " Length ............................................... 0x%04x\n",\r
215 Drhd->Header.Length\r
216 ));\r
217 DEBUG ((DEBUG_INFO,\r
218 " Flags ................................................ 0x%02x\n",\r
219 Drhd->Flags\r
220 ));\r
221 DEBUG ((DEBUG_INFO,\r
222 " INCLUDE_PCI_ALL .................................... 0x%02x\n",\r
223 Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL\r
224 ));\r
225 DEBUG ((DEBUG_INFO,\r
226 " Segment Number ....................................... 0x%04x\n",\r
227 Drhd->SegmentNumber\r
228 ));\r
229 DEBUG ((DEBUG_INFO,\r
230 " Register Base Address ................................ 0x%016lx\n",\r
231 Drhd->RegisterBaseAddress\r
232 ));\r
233\r
234 DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);\r
235 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);\r
236 while (DrhdLen > 0) {\r
237 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
238 DrhdLen -= DmarDeviceScopeEntry->Length;\r
239 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
240 }\r
241\r
242 DEBUG ((DEBUG_INFO,\r
243 " ***************************************************************************\n\n"\r
244 ));\r
245\r
246 return;\r
247}\r
248\r
249/**\r
250 Dump DMAR ACPI table.\r
251\r
252 @param[in] Dmar DMAR ACPI table\r
253**/\r
254VOID\r
255DumpAcpiDMAR (\r
256 IN EFI_ACPI_DMAR_HEADER *Dmar\r
257 )\r
258{\r
259 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
260 INTN DmarLen;\r
261\r
262 if (Dmar == NULL) {\r
263 return;\r
264 }\r
265\r
266 //\r
267 // Dump Dmar table\r
268 //\r
269 DEBUG ((DEBUG_INFO,\r
270 "*****************************************************************************\n"\r
271 ));\r
272 DEBUG ((DEBUG_INFO,\r
273 "* DMAR Table *\n"\r
274 ));\r
275 DEBUG ((DEBUG_INFO,\r
276 "*****************************************************************************\n"\r
277 ));\r
278\r
279 DEBUG ((DEBUG_INFO,\r
280 (sizeof(UINTN) == sizeof(UINT64)) ?\r
281 "DMAR address ............................................. 0x%016lx\n" :\r
282 "DMAR address ............................................. 0x%08x\n",\r
283 Dmar\r
284 ));\r
285\r
286 DEBUG ((DEBUG_INFO,\r
287 " Table Contents:\n"\r
288 ));\r
289 DEBUG ((DEBUG_INFO,\r
290 " Host Address Width ................................... 0x%02x\n",\r
291 Dmar->HostAddressWidth\r
292 ));\r
293 DEBUG ((DEBUG_INFO,\r
294 " Flags ................................................ 0x%02x\n",\r
295 Dmar->Flags\r
296 ));\r
297 DEBUG ((DEBUG_INFO,\r
298 " INTR_REMAP ......................................... 0x%02x\n",\r
299 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP\r
300 ));\r
301 DEBUG ((DEBUG_INFO,\r
302 " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",\r
303 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT\r
304 ));\r
6cea3c1b
JY
305 DEBUG ((DEBUG_INFO,\r
306 " DMA_CTRL_PLATFORM_OPT_IN_FLAG ...................... 0x%02x\n",\r
307 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_DMA_CTRL_PLATFORM_OPT_IN_FLAG\r
308 ));\r
a1e7cd0b
JY
309\r
310 DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);\r
311 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);\r
312 while (DmarLen > 0) {\r
313 switch (DmarHeader->Type) {\r
314 case EFI_ACPI_DMAR_TYPE_DRHD:\r
315 DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
316 break;\r
317 case EFI_ACPI_DMAR_TYPE_RMRR:\r
318 DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
319 break;\r
320 default:\r
321 break;\r
322 }\r
323 DmarLen -= DmarHeader->Length;\r
324 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
325 }\r
326\r
327 DEBUG ((DEBUG_INFO,\r
328 "*****************************************************************************\n\n"\r
329 ));\r
330\r
331 return;\r
332}\r
333\r
334/**\r
335 Get VTd engine number.\r
336\r
337 @param[in] AcpiDmarTable DMAR ACPI table\r
338\r
339 @return the VTd engine number.\r
340**/\r
341UINTN\r
342GetVtdEngineNumber (\r
343 IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable\r
344 )\r
345{\r
346 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
347 UINTN VtdIndex;\r
348\r
349 VtdIndex = 0;\r
350 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
351 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
352 switch (DmarHeader->Type) {\r
353 case EFI_ACPI_DMAR_TYPE_DRHD:\r
354 VtdIndex++;\r
355 break;\r
356 default:\r
357 break;\r
358 }\r
359 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
360 }\r
361 return VtdIndex ;\r
362}\r
363\r
364/**\r
365 Process DMAR DHRD table.\r
366\r
367 @param[in] VTdInfo The VTd engine context information.\r
368 @param[in] VtdIndex The index of VTd engine.\r
369 @param[in] DmarDrhd The DRHD table.\r
370**/\r
371VOID\r
372ProcessDhrd (\r
373 IN VTD_INFO *VTdInfo,\r
374 IN UINTN VtdIndex,\r
375 IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd\r
376 )\r
377{\r
378 DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));\r
379 VTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;\r
380}\r
381\r
382/**\r
383 Parse DMAR DRHD table.\r
384\r
385 @param[in] AcpiDmarTable DMAR ACPI table\r
386\r
387 @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
388**/\r
389EFI_STATUS\r
390ParseDmarAcpiTableDrhd (\r
391 IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable\r
392 )\r
393{\r
394 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
395 UINTN VtdUnitNumber;\r
396 UINTN VtdIndex;\r
397 VTD_INFO *VTdInfo;\r
398\r
399 VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);\r
400 if (VtdUnitNumber == 0) {\r
401 return EFI_UNSUPPORTED;\r
402 }\r
403\r
404 VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));\r
405 ASSERT(VTdInfo != NULL);\r
406 if (VTdInfo == NULL) {\r
407 return EFI_OUT_OF_RESOURCES;\r
408 }\r
409\r
410 //\r
411 // Initialize the engine mask to all.\r
412 //\r
413 VTdInfo->AcpiDmarTable = AcpiDmarTable;\r
414 VTdInfo->EngineMask = LShiftU64 (1, VtdUnitNumber) - 1;\r
415 VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;\r
416 VTdInfo->VTdEngineCount = VtdUnitNumber;\r
417\r
418 VtdIndex = 0;\r
419 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
420 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
421 switch (DmarHeader->Type) {\r
422 case EFI_ACPI_DMAR_TYPE_DRHD:\r
423 ASSERT (VtdIndex < VtdUnitNumber);\r
424 ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
425 VtdIndex++;\r
426\r
427 break;\r
428\r
429 default:\r
430 break;\r
431 }\r
432 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
433 }\r
434 ASSERT (VtdIndex == VtdUnitNumber);\r
435\r
436 return EFI_SUCCESS;\r
437}\r
438\r
439/**\r
440 Return the VTd engine index according to the Segment and DevScopeEntry.\r
441\r
442 @param AcpiDmarTable DMAR ACPI table\r
443 @param Segment The segment of the VTd engine\r
444 @param DevScopeEntry The DevScopeEntry of the VTd engine\r
445\r
446 @return The VTd engine index according to the Segment and DevScopeEntry.\r
447 @retval -1 The VTd engine is not found.\r
448**/\r
449UINTN\r
450GetVTdEngineFromDevScopeEntry (\r
451 IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,\r
452 IN UINT16 Segment,\r
453 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry\r
454 )\r
455{\r
456 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
457 UINTN VtdIndex;\r
458 EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;\r
459 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;\r
460\r
461 VtdIndex = 0;\r
462 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
463 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
464 switch (DmarHeader->Type) {\r
465 case EFI_ACPI_DMAR_TYPE_DRHD:\r
466 DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;\r
467 if (DmarDrhd->SegmentNumber != Segment) {\r
468 // Mismatch\r
469 break;\r
470 }\r
471 if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||\r
472 ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {\r
473 // No DevScopeEntry\r
474 // Do not handle PCI_ALL\r
475 break;\r
476 }\r
477 ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));\r
478 while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {\r
479 if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&\r
480 (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {\r
481 return VtdIndex;\r
482 }\r
483 ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);\r
484 }\r
485 break;\r
486 default:\r
487 break;\r
488 }\r
489 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
490 }\r
491 return (UINTN)-1;\r
492}\r
493\r
494/**\r
495 Process DMAR RMRR table.\r
496\r
497 @param[in] VTdInfo The VTd engine context information.\r
498 @param[in] DmarRmrr The RMRR table.\r
499**/\r
500VOID\r
501ProcessRmrr (\r
502 IN VTD_INFO *VTdInfo,\r
503 IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr\r
504 )\r
505{\r
506 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
507 UINTN VTdIndex;\r
508 UINT64 RmrrMask;\r
509 UINTN LowBottom;\r
510 UINTN LowTop;\r
511 UINTN HighBottom;\r
512 UINT64 HighTop;\r
513 EFI_ACPI_DMAR_HEADER *AcpiDmarTable;\r
514\r
515 AcpiDmarTable = VTdInfo->AcpiDmarTable;\r
516\r
517 DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));\r
518\r
519 if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||\r
520 (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {\r
521 return ;\r
522 }\r
523\r
524 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));\r
525 while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {\r
526 ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);\r
527\r
528 VTdIndex = GetVTdEngineFromDevScopeEntry (AcpiDmarTable, DmarRmrr->SegmentNumber, DmarDevScopeEntry);\r
529 if (VTdIndex != (UINTN)-1) {\r
530 RmrrMask = LShiftU64 (1, VTdIndex);\r
531\r
532 LowBottom = 0;\r
533 LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;\r
534 HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;\r
b2725f57 535 HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);\r
a1e7cd0b
JY
536\r
537 SetDmaProtectedRange (\r
538 VTdInfo,\r
539 RmrrMask,\r
540 0,\r
541 (UINT32)(LowTop - LowBottom),\r
542 HighBottom,\r
543 HighTop - HighBottom\r
544 );\r
545\r
546 //\r
547 // Remove the engine from the engine mask.\r
548 // The assumption is that any other PEI driver does not access\r
549 // the device covered by this engine.\r
550 //\r
551 VTdInfo->EngineMask = VTdInfo->EngineMask & (~RmrrMask);\r
552 }\r
553\r
554 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
555 }\r
556}\r
557\r
558/**\r
559 Parse DMAR DRHD table.\r
560\r
561 @param[in] VTdInfo The VTd engine context information.\r
562**/\r
563VOID\r
564ParseDmarAcpiTableRmrr (\r
565 IN VTD_INFO *VTdInfo\r
566 )\r
567{\r
568 EFI_ACPI_DMAR_HEADER *AcpiDmarTable;\r
569 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
570\r
571 AcpiDmarTable = VTdInfo->AcpiDmarTable;\r
572\r
573 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
574 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
575 switch (DmarHeader->Type) {\r
576 case EFI_ACPI_DMAR_TYPE_RMRR:\r
577 ProcessRmrr (VTdInfo, (EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
578 break;\r
579 default:\r
580 break;\r
581 }\r
582 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
583 }\r
584}\r