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