]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
IntelSiliconPkg IntelVTdDxe: Remove mVtdHostAddressWidthMask
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / DmarTable.c
CommitLineData
a1e7cd0b
JY
1/** @file\r
2\r
3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
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
305\r
306 DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);\r
307 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);\r
308 while (DmarLen > 0) {\r
309 switch (DmarHeader->Type) {\r
310 case EFI_ACPI_DMAR_TYPE_DRHD:\r
311 DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
312 break;\r
313 case EFI_ACPI_DMAR_TYPE_RMRR:\r
314 DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
315 break;\r
316 default:\r
317 break;\r
318 }\r
319 DmarLen -= DmarHeader->Length;\r
320 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
321 }\r
322\r
323 DEBUG ((DEBUG_INFO,\r
324 "*****************************************************************************\n\n"\r
325 ));\r
326\r
327 return;\r
328}\r
329\r
330/**\r
331 Get VTd engine number.\r
332\r
333 @param[in] AcpiDmarTable DMAR ACPI table\r
334\r
335 @return the VTd engine number.\r
336**/\r
337UINTN\r
338GetVtdEngineNumber (\r
339 IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable\r
340 )\r
341{\r
342 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
343 UINTN VtdIndex;\r
344\r
345 VtdIndex = 0;\r
346 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
347 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
348 switch (DmarHeader->Type) {\r
349 case EFI_ACPI_DMAR_TYPE_DRHD:\r
350 VtdIndex++;\r
351 break;\r
352 default:\r
353 break;\r
354 }\r
355 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
356 }\r
357 return VtdIndex ;\r
358}\r
359\r
360/**\r
361 Process DMAR DHRD table.\r
362\r
363 @param[in] VTdInfo The VTd engine context information.\r
364 @param[in] VtdIndex The index of VTd engine.\r
365 @param[in] DmarDrhd The DRHD table.\r
366**/\r
367VOID\r
368ProcessDhrd (\r
369 IN VTD_INFO *VTdInfo,\r
370 IN UINTN VtdIndex,\r
371 IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd\r
372 )\r
373{\r
374 DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));\r
375 VTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;\r
376}\r
377\r
378/**\r
379 Parse DMAR DRHD table.\r
380\r
381 @param[in] AcpiDmarTable DMAR ACPI table\r
382\r
383 @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
384**/\r
385EFI_STATUS\r
386ParseDmarAcpiTableDrhd (\r
387 IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable\r
388 )\r
389{\r
390 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
391 UINTN VtdUnitNumber;\r
392 UINTN VtdIndex;\r
393 VTD_INFO *VTdInfo;\r
394\r
395 VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);\r
396 if (VtdUnitNumber == 0) {\r
397 return EFI_UNSUPPORTED;\r
398 }\r
399\r
400 VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));\r
401 ASSERT(VTdInfo != NULL);\r
402 if (VTdInfo == NULL) {\r
403 return EFI_OUT_OF_RESOURCES;\r
404 }\r
405\r
406 //\r
407 // Initialize the engine mask to all.\r
408 //\r
409 VTdInfo->AcpiDmarTable = AcpiDmarTable;\r
410 VTdInfo->EngineMask = LShiftU64 (1, VtdUnitNumber) - 1;\r
411 VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;\r
412 VTdInfo->VTdEngineCount = VtdUnitNumber;\r
413\r
414 VtdIndex = 0;\r
415 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
416 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
417 switch (DmarHeader->Type) {\r
418 case EFI_ACPI_DMAR_TYPE_DRHD:\r
419 ASSERT (VtdIndex < VtdUnitNumber);\r
420 ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
421 VtdIndex++;\r
422\r
423 break;\r
424\r
425 default:\r
426 break;\r
427 }\r
428 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
429 }\r
430 ASSERT (VtdIndex == VtdUnitNumber);\r
431\r
432 return EFI_SUCCESS;\r
433}\r
434\r
435/**\r
436 Return the VTd engine index according to the Segment and DevScopeEntry.\r
437\r
438 @param AcpiDmarTable DMAR ACPI table\r
439 @param Segment The segment of the VTd engine\r
440 @param DevScopeEntry The DevScopeEntry of the VTd engine\r
441\r
442 @return The VTd engine index according to the Segment and DevScopeEntry.\r
443 @retval -1 The VTd engine is not found.\r
444**/\r
445UINTN\r
446GetVTdEngineFromDevScopeEntry (\r
447 IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,\r
448 IN UINT16 Segment,\r
449 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry\r
450 )\r
451{\r
452 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
453 UINTN VtdIndex;\r
454 EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;\r
455 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;\r
456\r
457 VtdIndex = 0;\r
458 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
459 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
460 switch (DmarHeader->Type) {\r
461 case EFI_ACPI_DMAR_TYPE_DRHD:\r
462 DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;\r
463 if (DmarDrhd->SegmentNumber != Segment) {\r
464 // Mismatch\r
465 break;\r
466 }\r
467 if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||\r
468 ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {\r
469 // No DevScopeEntry\r
470 // Do not handle PCI_ALL\r
471 break;\r
472 }\r
473 ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));\r
474 while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {\r
475 if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&\r
476 (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {\r
477 return VtdIndex;\r
478 }\r
479 ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);\r
480 }\r
481 break;\r
482 default:\r
483 break;\r
484 }\r
485 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
486 }\r
487 return (UINTN)-1;\r
488}\r
489\r
490/**\r
491 Process DMAR RMRR table.\r
492\r
493 @param[in] VTdInfo The VTd engine context information.\r
494 @param[in] DmarRmrr The RMRR table.\r
495**/\r
496VOID\r
497ProcessRmrr (\r
498 IN VTD_INFO *VTdInfo,\r
499 IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr\r
500 )\r
501{\r
502 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
503 UINTN VTdIndex;\r
504 UINT64 RmrrMask;\r
505 UINTN LowBottom;\r
506 UINTN LowTop;\r
507 UINTN HighBottom;\r
508 UINT64 HighTop;\r
509 EFI_ACPI_DMAR_HEADER *AcpiDmarTable;\r
510\r
511 AcpiDmarTable = VTdInfo->AcpiDmarTable;\r
512\r
513 DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));\r
514\r
515 if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||\r
516 (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {\r
517 return ;\r
518 }\r
519\r
520 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));\r
521 while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {\r
522 ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);\r
523\r
524 VTdIndex = GetVTdEngineFromDevScopeEntry (AcpiDmarTable, DmarRmrr->SegmentNumber, DmarDevScopeEntry);\r
525 if (VTdIndex != (UINTN)-1) {\r
526 RmrrMask = LShiftU64 (1, VTdIndex);\r
527\r
528 LowBottom = 0;\r
529 LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;\r
530 HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;\r
531 HighTop = GetTopMemory ();\r
532\r
533 SetDmaProtectedRange (\r
534 VTdInfo,\r
535 RmrrMask,\r
536 0,\r
537 (UINT32)(LowTop - LowBottom),\r
538 HighBottom,\r
539 HighTop - HighBottom\r
540 );\r
541\r
542 //\r
543 // Remove the engine from the engine mask.\r
544 // The assumption is that any other PEI driver does not access\r
545 // the device covered by this engine.\r
546 //\r
547 VTdInfo->EngineMask = VTdInfo->EngineMask & (~RmrrMask);\r
548 }\r
549\r
550 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
551 }\r
552}\r
553\r
554/**\r
555 Parse DMAR DRHD table.\r
556\r
557 @param[in] VTdInfo The VTd engine context information.\r
558**/\r
559VOID\r
560ParseDmarAcpiTableRmrr (\r
561 IN VTD_INFO *VTdInfo\r
562 )\r
563{\r
564 EFI_ACPI_DMAR_HEADER *AcpiDmarTable;\r
565 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
566\r
567 AcpiDmarTable = VTdInfo->AcpiDmarTable;\r
568\r
569 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));\r
570 while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {\r
571 switch (DmarHeader->Type) {\r
572 case EFI_ACPI_DMAR_TYPE_RMRR:\r
573 ProcessRmrr (VTdInfo, (EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
574 break;\r
575 default:\r
576 break;\r
577 }\r
578 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
579 }\r
580}\r