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