]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/IntelVTdDxe/DmarAcpiTable.c
IntelSiliconPkg/header: update PlatformVtdPolicy
[mirror_edk2.git] / IntelSiliconPkg / IntelVTdDxe / DmarAcpiTable.c
CommitLineData
c049fc99
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 "DmaProtection.h"\r
15\r
16#pragma pack(1)\r
17\r
18typedef struct {\r
19 EFI_ACPI_DESCRIPTION_HEADER Header;\r
20 UINT32 Entry;\r
21} RSDT_TABLE;\r
22\r
23typedef struct {\r
24 EFI_ACPI_DESCRIPTION_HEADER Header;\r
25 UINT64 Entry;\r
26} XSDT_TABLE;\r
27\r
28#pragma pack()\r
29\r
30EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;\r
31\r
32/**\r
33 Dump DMAR DeviceScopeEntry.\r
34\r
35 @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry\r
36**/\r
37VOID\r
38DumpDmarDeviceScopeEntry (\r
39 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry\r
40 )\r
41{\r
42 UINTN PciPathNumber;\r
43 UINTN PciPathIndex;\r
44 EFI_ACPI_DMAR_PCI_PATH *PciPath;\r
45\r
46 if (DmarDeviceScopeEntry == NULL) {\r
47 return;\r
48 }\r
49\r
50 DEBUG ((DEBUG_INFO,\r
51 " *************************************************************************\n"\r
52 " * DMA-Remapping Device Scope Entry Structure *\n"\r
53 " *************************************************************************\n"\r
54 ));\r
55 DEBUG ((DEBUG_INFO,\r
56 (sizeof(UINTN) == sizeof(UINT64)) ?\r
57 " DMAR Device Scope Entry address ...................... 0x%016lx\n" :\r
58 " DMAR Device Scope Entry address ...................... 0x%08x\n",\r
59 DmarDeviceScopeEntry\r
60 ));\r
61 DEBUG ((DEBUG_INFO,\r
62 " Device Scope Entry Type ............................ 0x%02x\n",\r
63 DmarDeviceScopeEntry->Type\r
64 ));\r
65 switch (DmarDeviceScopeEntry->Type) {\r
66 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
67 DEBUG ((DEBUG_INFO,\r
68 " PCI Endpoint Device\n"\r
69 ));\r
70 break;\r
71 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
72 DEBUG ((DEBUG_INFO,\r
73 " PCI Sub-hierachy\n"\r
74 ));\r
75 break;\r
76 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
77 DEBUG ((DEBUG_INFO,\r
78 " IOAPIC\n"\r
79 ));\r
80 break;\r
81 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
82 DEBUG ((DEBUG_INFO,\r
83 " MSI Capable HPET\n"\r
84 ));\r
85 break;\r
86 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
87 DEBUG ((DEBUG_INFO,\r
88 " ACPI Namespace Device\n"\r
89 ));\r
90 break;\r
91 default:\r
92 break;\r
93 }\r
94 DEBUG ((DEBUG_INFO,\r
95 " Length ............................................. 0x%02x\n",\r
96 DmarDeviceScopeEntry->Length\r
97 ));\r
98 DEBUG ((DEBUG_INFO,\r
99 " Enumeration ID ..................................... 0x%02x\n",\r
100 DmarDeviceScopeEntry->EnumerationId\r
101 ));\r
102 DEBUG ((DEBUG_INFO,\r
103 " Starting Bus Number ................................ 0x%02x\n",\r
104 DmarDeviceScopeEntry->StartBusNumber\r
105 ));\r
106\r
107 PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);\r
108 PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);\r
109 for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {\r
110 DEBUG ((DEBUG_INFO,\r
111 " Device ............................................. 0x%02x\n",\r
112 PciPath[PciPathIndex].Device\r
113 ));\r
114 DEBUG ((DEBUG_INFO,\r
115 " Function ........................................... 0x%02x\n",\r
116 PciPath[PciPathIndex].Function\r
117 ));\r
118 }\r
119\r
120 DEBUG ((DEBUG_INFO,\r
121 " *************************************************************************\n\n"\r
122 ));\r
123\r
124 return;\r
125}\r
126\r
127/**\r
128 Dump DMAR ANDD table.\r
129\r
130 @param[in] Andd DMAR ANDD table\r
131**/\r
132VOID\r
133DumpDmarAndd (\r
134 IN EFI_ACPI_DMAR_ANDD_HEADER *Andd\r
135 )\r
136{\r
137 if (Andd == NULL) {\r
138 return;\r
139 }\r
140\r
141 DEBUG ((DEBUG_INFO,\r
142 " ***************************************************************************\n"\r
143 " * ACPI Name-space Device Declaration Structure *\n"\r
144 " ***************************************************************************\n"\r
145 ));\r
146 DEBUG ((DEBUG_INFO,\r
147 (sizeof(UINTN) == sizeof(UINT64)) ?\r
148 " ANDD address ........................................... 0x%016lx\n" :\r
149 " ANDD address ........................................... 0x%08x\n",\r
150 Andd\r
151 ));\r
152 DEBUG ((DEBUG_INFO,\r
153 " Type ................................................. 0x%04x\n",\r
154 Andd->Header.Type\r
155 ));\r
156 DEBUG ((DEBUG_INFO,\r
157 " Length ............................................... 0x%04x\n",\r
158 Andd->Header.Length\r
159 ));\r
160 DEBUG ((DEBUG_INFO,\r
161 " ACPI Device Number ................................... 0x%02x\n",\r
162 Andd->AcpiDeviceNumber\r
163 ));\r
164 DEBUG ((DEBUG_INFO,\r
165 " ACPI Object Name ..................................... '%a'\n",\r
166 (Andd + 1)\r
167 ));\r
168\r
169 DEBUG ((DEBUG_INFO,\r
170 " ***************************************************************************\n\n"\r
171 ));\r
172\r
173 return;\r
174}\r
175\r
176/**\r
177 Dump DMAR RHSA table.\r
178\r
179 @param[in] Rhsa DMAR RHSA table\r
180**/\r
181VOID\r
182DumpDmarRhsa (\r
183 IN EFI_ACPI_DMAR_RHSA_HEADER *Rhsa\r
184 )\r
185{\r
186 if (Rhsa == NULL) {\r
187 return;\r
188 }\r
189\r
190 DEBUG ((DEBUG_INFO,\r
191 " ***************************************************************************\n"\r
192 " * Remapping Hardware Status Affinity Structure *\n"\r
193 " ***************************************************************************\n"\r
194 ));\r
195 DEBUG ((DEBUG_INFO,\r
196 (sizeof(UINTN) == sizeof(UINT64)) ?\r
197 " RHSA address ........................................... 0x%016lx\n" :\r
198 " RHSA address ........................................... 0x%08x\n",\r
199 Rhsa\r
200 ));\r
201 DEBUG ((DEBUG_INFO,\r
202 " Type ................................................. 0x%04x\n",\r
203 Rhsa->Header.Type\r
204 ));\r
205 DEBUG ((DEBUG_INFO,\r
206 " Length ............................................... 0x%04x\n",\r
207 Rhsa->Header.Length\r
208 ));\r
209 DEBUG ((DEBUG_INFO,\r
210 " Register Base Address ................................ 0x%016lx\n",\r
211 Rhsa->RegisterBaseAddress\r
212 ));\r
213 DEBUG ((DEBUG_INFO,\r
214 " Proximity Domain ..................................... 0x%08x\n",\r
215 Rhsa->ProximityDomain\r
216 ));\r
217\r
218 DEBUG ((DEBUG_INFO,\r
219 " ***************************************************************************\n\n"\r
220 ));\r
221\r
222 return;\r
223}\r
224\r
225/**\r
226 Dump DMAR ATSR table.\r
227\r
228 @param[in] Atsr DMAR ATSR table\r
229**/\r
230VOID\r
231DumpDmarAtsr (\r
232 IN EFI_ACPI_DMAR_ATSR_HEADER *Atsr\r
233 )\r
234{\r
235 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
236 INTN AtsrLen;\r
237\r
238 if (Atsr == NULL) {\r
239 return;\r
240 }\r
241\r
242 DEBUG ((DEBUG_INFO,\r
243 " ***************************************************************************\n"\r
244 " * Root Port ATS Capability Reporting Structure *\n"\r
245 " ***************************************************************************\n"\r
246 ));\r
247 DEBUG ((DEBUG_INFO,\r
248 (sizeof(UINTN) == sizeof(UINT64)) ?\r
249 " ATSR address ........................................... 0x%016lx\n" :\r
250 " ATSR address ........................................... 0x%08x\n",\r
251 Atsr\r
252 ));\r
253 DEBUG ((DEBUG_INFO,\r
254 " Type ................................................. 0x%04x\n",\r
255 Atsr->Header.Type\r
256 ));\r
257 DEBUG ((DEBUG_INFO,\r
258 " Length ............................................... 0x%04x\n",\r
259 Atsr->Header.Length\r
260 ));\r
261 DEBUG ((DEBUG_INFO,\r
262 " Flags ................................................ 0x%02x\n",\r
263 Atsr->Flags\r
264 ));\r
265 DEBUG ((DEBUG_INFO,\r
266 " ALL_PORTS .......................................... 0x%02x\n",\r
267 Atsr->Flags & EFI_ACPI_DMAR_ATSR_FLAGS_ALL_PORTS\r
268 ));\r
269 DEBUG ((DEBUG_INFO,\r
270 " Segment Number ....................................... 0x%04x\n",\r
271 Atsr->SegmentNumber\r
272 ));\r
273\r
274 AtsrLen = Atsr->Header.Length - sizeof(EFI_ACPI_DMAR_ATSR_HEADER);\r
275 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Atsr + 1);\r
276 while (AtsrLen > 0) {\r
277 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
278 AtsrLen -= DmarDeviceScopeEntry->Length;\r
279 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
280 }\r
281\r
282 DEBUG ((DEBUG_INFO,\r
283 " ***************************************************************************\n\n"\r
284 ));\r
285\r
286 return;\r
287}\r
288\r
289/**\r
290 Dump DMAR RMRR table.\r
291\r
292 @param[in] Rmrr DMAR RMRR table\r
293**/\r
294VOID\r
295DumpDmarRmrr (\r
296 IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr\r
297 )\r
298{\r
299 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
300 INTN RmrrLen;\r
301\r
302 if (Rmrr == NULL) {\r
303 return;\r
304 }\r
305\r
306 DEBUG ((DEBUG_INFO,\r
307 " ***************************************************************************\n"\r
308 " * Reserved Memory Region Reporting Structure *\n"\r
309 " ***************************************************************************\n"\r
310 ));\r
311 DEBUG ((DEBUG_INFO,\r
312 (sizeof(UINTN) == sizeof(UINT64)) ?\r
313 " RMRR address ........................................... 0x%016lx\n" :\r
314 " RMRR address ........................................... 0x%08x\n",\r
315 Rmrr\r
316 ));\r
317 DEBUG ((DEBUG_INFO,\r
318 " Type ................................................. 0x%04x\n",\r
319 Rmrr->Header.Type\r
320 ));\r
321 DEBUG ((DEBUG_INFO,\r
322 " Length ............................................... 0x%04x\n",\r
323 Rmrr->Header.Length\r
324 ));\r
325 DEBUG ((DEBUG_INFO,\r
326 " Segment Number ....................................... 0x%04x\n",\r
327 Rmrr->SegmentNumber\r
328 ));\r
329 DEBUG ((DEBUG_INFO,\r
330 " Reserved Memory Region Base Address .................. 0x%016lx\n",\r
331 Rmrr->ReservedMemoryRegionBaseAddress\r
332 ));\r
333 DEBUG ((DEBUG_INFO,\r
334 " Reserved Memory Region Limit Address ................. 0x%016lx\n",\r
335 Rmrr->ReservedMemoryRegionLimitAddress\r
336 ));\r
337\r
338 RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);\r
339 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);\r
340 while (RmrrLen > 0) {\r
341 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
342 RmrrLen -= DmarDeviceScopeEntry->Length;\r
343 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
344 }\r
345\r
346 DEBUG ((DEBUG_INFO,\r
347 " ***************************************************************************\n\n"\r
348 ));\r
349\r
350 return;\r
351}\r
352\r
353/**\r
354 Dump DMAR DRHD table.\r
355\r
356 @param[in] Drhd DMAR DRHD table\r
357**/\r
358VOID\r
359DumpDmarDrhd (\r
360 IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd\r
361 )\r
362{\r
363 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;\r
364 INTN DrhdLen;\r
365\r
366 if (Drhd == NULL) {\r
367 return;\r
368 }\r
369\r
370 DEBUG ((DEBUG_INFO,\r
371 " ***************************************************************************\n"\r
372 " * DMA-Remapping Hardware Definition Structure *\n"\r
373 " ***************************************************************************\n"\r
374 ));\r
375 DEBUG ((DEBUG_INFO,\r
376 (sizeof(UINTN) == sizeof(UINT64)) ?\r
377 " DRHD address ........................................... 0x%016lx\n" :\r
378 " DRHD address ........................................... 0x%08x\n",\r
379 Drhd\r
380 ));\r
381 DEBUG ((DEBUG_INFO,\r
382 " Type ................................................. 0x%04x\n",\r
383 Drhd->Header.Type\r
384 ));\r
385 DEBUG ((DEBUG_INFO,\r
386 " Length ............................................... 0x%04x\n",\r
387 Drhd->Header.Length\r
388 ));\r
389 DEBUG ((DEBUG_INFO,\r
390 " Flags ................................................ 0x%02x\n",\r
391 Drhd->Flags\r
392 ));\r
393 DEBUG ((DEBUG_INFO,\r
394 " INCLUDE_PCI_ALL .................................... 0x%02x\n",\r
395 Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL\r
396 ));\r
397 DEBUG ((DEBUG_INFO,\r
398 " Segment Number ....................................... 0x%04x\n",\r
399 Drhd->SegmentNumber\r
400 ));\r
401 DEBUG ((DEBUG_INFO,\r
402 " Register Base Address ................................ 0x%016lx\n",\r
403 Drhd->RegisterBaseAddress\r
404 ));\r
405\r
406 DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);\r
407 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);\r
408 while (DrhdLen > 0) {\r
409 DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);\r
410 DrhdLen -= DmarDeviceScopeEntry->Length;\r
411 DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);\r
412 }\r
413\r
414 DEBUG ((DEBUG_INFO,\r
415 " ***************************************************************************\n\n"\r
416 ));\r
417\r
418 return;\r
419}\r
420\r
421/**\r
422 Dump DMAR ACPI table.\r
423\r
424 @param[in] Dmar DMAR ACPI table\r
425**/\r
426VOID\r
427DumpAcpiDMAR (\r
428 IN EFI_ACPI_DMAR_HEADER *Dmar\r
429 )\r
430{\r
431 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
432 INTN DmarLen;\r
433\r
434 if (Dmar == NULL) {\r
435 return;\r
436 }\r
437\r
438 //\r
439 // Dump Dmar table\r
440 //\r
441 DEBUG ((DEBUG_INFO,\r
442 "*****************************************************************************\n"\r
443 "* DMAR Table *\n"\r
444 "*****************************************************************************\n"\r
445 ));\r
446\r
447 DEBUG ((DEBUG_INFO,\r
448 (sizeof(UINTN) == sizeof(UINT64)) ?\r
449 "DMAR address ............................................. 0x%016lx\n" :\r
450 "DMAR address ............................................. 0x%08x\n",\r
451 Dmar\r
452 ));\r
453\r
454 DEBUG ((DEBUG_INFO,\r
455 " Table Contents:\n"\r
456 ));\r
457 DEBUG ((DEBUG_INFO,\r
458 " Host Address Width ................................... 0x%02x\n",\r
459 Dmar->HostAddressWidth\r
460 ));\r
461 DEBUG ((DEBUG_INFO,\r
462 " Flags ................................................ 0x%02x\n",\r
463 Dmar->Flags\r
464 ));\r
465 DEBUG ((DEBUG_INFO,\r
466 " INTR_REMAP ......................................... 0x%02x\n",\r
467 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP\r
468 ));\r
469 DEBUG ((DEBUG_INFO,\r
470 " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",\r
471 Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT\r
472 ));\r
473\r
474 DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);\r
475 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);\r
476 while (DmarLen > 0) {\r
477 switch (DmarHeader->Type) {\r
478 case EFI_ACPI_DMAR_TYPE_DRHD:\r
479 DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
480 break;\r
481 case EFI_ACPI_DMAR_TYPE_RMRR:\r
482 DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
483 break;\r
484 case EFI_ACPI_DMAR_TYPE_ATSR:\r
485 DumpDmarAtsr ((EFI_ACPI_DMAR_ATSR_HEADER *)DmarHeader);\r
486 break;\r
487 case EFI_ACPI_DMAR_TYPE_RHSA:\r
488 DumpDmarRhsa ((EFI_ACPI_DMAR_RHSA_HEADER *)DmarHeader);\r
489 break;\r
490 case EFI_ACPI_DMAR_TYPE_ANDD:\r
491 DumpDmarAndd ((EFI_ACPI_DMAR_ANDD_HEADER *)DmarHeader);\r
492 break;\r
493 default:\r
494 break;\r
495 }\r
496 DmarLen -= DmarHeader->Length;\r
497 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
498 }\r
499\r
500 DEBUG ((DEBUG_INFO,\r
501 "*****************************************************************************\n\n"\r
502 ));\r
503\r
504 return;\r
505}\r
506\r
507/**\r
508 Dump DMAR ACPI table.\r
509**/\r
510VOID\r
511VtdDumpDmarTable (\r
512 VOID\r
513 )\r
514{\r
515 DumpAcpiDMAR ((EFI_ACPI_DMAR_HEADER *)(UINTN)mAcpiDmarTable);\r
516}\r
517\r
518/**\r
519 Get PCI device information from DMAR DevScopeEntry.\r
520\r
521 @param[in] Segment The segment number.\r
522 @param[in] DmarDevScopeEntry DMAR DevScopeEntry\r
523 @param[out] Bus The bus number.\r
524 @param[out] Device The device number.\r
525 @param[out] Function The function number.\r
526\r
527 @retval EFI_SUCCESS The PCI device information is returned.\r
528**/\r
529EFI_STATUS\r
530GetPciBusDeviceFunction (\r
531 IN UINT16 Segment,\r
532 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,\r
533 OUT UINT8 *Bus,\r
534 OUT UINT8 *Device,\r
535 OUT UINT8 *Function\r
536 )\r
537{\r
538 EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;\r
539 UINT8 MyBus;\r
540 UINT8 MyDevice;\r
541 UINT8 MyFunction;\r
542\r
543 DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *)((UINTN)(DmarDevScopeEntry + 1));\r
544 MyBus = DmarDevScopeEntry->StartBusNumber;\r
545 MyDevice = DmarPciPath->Device;\r
546 MyFunction = DmarPciPath->Function;\r
547\r
548 switch (DmarDevScopeEntry->Type) {\r
549 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
550 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
551 while ((UINTN)DmarPciPath < (UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length) {\r
552 MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
553 MyDevice = DmarPciPath->Device;\r
554 MyFunction = DmarPciPath->Function;\r
555 DmarPciPath ++;\r
556 }\r
557 break;\r
558 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
559 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
560 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
561 break;\r
562 }\r
563\r
564 *Bus = MyBus;\r
565 *Device = MyDevice;\r
566 *Function = MyFunction;\r
567\r
568 return EFI_SUCCESS;\r
569}\r
570\r
571/**\r
572 Process DMAR DHRD table.\r
573\r
574 @param[in] VtdIndex The index of VTd engine.\r
575 @param[in] DmarDrhd The DRHD table.\r
576\r
577 @retval EFI_SUCCESS The DRHD table is processed.\r
578**/\r
579EFI_STATUS\r
580ProcessDhrd (\r
581 IN UINTN VtdIndex,\r
582 IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd\r
583 )\r
584{\r
585 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
586 UINT8 Bus;\r
587 UINT8 Device;\r
588 UINT8 Function;\r
589 UINT8 SecondaryBusNumber;\r
590 EFI_STATUS Status;\r
591 VTD_SOURCE_ID SourceId;\r
592 BOOLEAN IsRealPciDevice;\r
593\r
594 mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress = (UINTN)DmarDrhd->RegisterBaseAddress;\r
595 DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));\r
596\r
597 mVtdUnitInformation[VtdIndex].Segment = DmarDrhd->SegmentNumber;\r
598\r
599 if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {\r
600 mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE;\r
601 DEBUG ((DEBUG_INFO," ProcessDhrd: with INCLUDE ALL\n"));\r
602\r
603 Status = ScanPciBus(VtdIndex, DmarDrhd->SegmentNumber, 0);\r
604 if (EFI_ERROR (Status)) {\r
605 return Status;\r
606 }\r
607 } else {\r
608 mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE;\r
609 DEBUG ((DEBUG_INFO," ProcessDhrd: without INCLUDE ALL\n"));\r
610 }\r
611\r
612 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));\r
613 while ((UINTN)DmarDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {\r
614\r
615 Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);\r
616 if (EFI_ERROR (Status)) {\r
617 return Status;\r
618 }\r
619 switch (DmarDevScopeEntry->Type) {\r
620 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
621 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
622 IsRealPciDevice = TRUE;\r
623 break;\r
624 default:\r
625 IsRealPciDevice = FALSE;\r
626 break;\r
627 }\r
628\r
629 DEBUG ((DEBUG_INFO," ProcessDhrd: "));\r
630 switch (DmarDevScopeEntry->Type) {\r
631 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
632 DEBUG ((DEBUG_INFO,"PCI Endpoint"));\r
633 break;\r
634 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
635 DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));\r
636 break;\r
637 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
638 DEBUG ((DEBUG_INFO,"IOAPIC"));\r
639 break;\r
640 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
641 DEBUG ((DEBUG_INFO,"MSI Capable HPET"));\r
642 break;\r
643 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
644 DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));\r
645 break;\r
646 }\r
647 DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumber, Bus, Device, Function));\r
648\r
649 SourceId.Bits.Bus = Bus;\r
650 SourceId.Bits.Device = Device;\r
651 SourceId.Bits.Function = Function;\r
652\r
653 Status = RegisterPciDevice (VtdIndex, DmarDrhd->SegmentNumber, SourceId, IsRealPciDevice, TRUE);\r
654 if (EFI_ERROR (Status)) {\r
655 //\r
656 // There might be duplication for special device other than standard PCI device.\r
657 //\r
658 switch (DmarDevScopeEntry->Type) {\r
659 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
660 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
661 return Status;\r
662 }\r
663 }\r
664\r
665 switch (DmarDevScopeEntry->Type) {\r
666 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
667 SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DmarDrhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
668 Status = ScanPciBus (VtdIndex, DmarDrhd->SegmentNumber, SecondaryBusNumber);\r
669 if (EFI_ERROR (Status)) {\r
670 return Status;\r
671 }\r
672 break;\r
673 default:\r
674 break;\r
675 }\r
676\r
677 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
678 }\r
679\r
680 return EFI_SUCCESS;\r
681}\r
682\r
683/**\r
684 Process DMAR RMRR table.\r
685\r
686 @param[in] DmarRmrr The RMRR table.\r
687\r
688 @retval EFI_SUCCESS The RMRR table is processed.\r
689**/\r
690EFI_STATUS\r
691ProcessRmrr (\r
692 IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr\r
693 )\r
694{\r
695 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
696 UINT8 Bus;\r
697 UINT8 Device;\r
698 UINT8 Function;\r
699 EFI_STATUS Status;\r
700 VTD_SOURCE_ID SourceId;\r
701\r
702 DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));\r
703\r
704 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));\r
705 while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {\r
706 if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) {\r
707 DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%x] \n", DmarDevScopeEntry->Type));\r
708 return EFI_DEVICE_ERROR;\r
709 }\r
710\r
711 Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);\r
712 if (EFI_ERROR (Status)) {\r
713 return Status;\r
714 }\r
715\r
716 DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function));\r
717\r
718 SourceId.Bits.Bus = Bus;\r
719 SourceId.Bits.Device = Device;\r
720 SourceId.Bits.Function = Function;\r
721 Status = SetAccessAttribute (\r
722 DmarRmrr->SegmentNumber,\r
723 SourceId,\r
724 DmarRmrr->ReservedMemoryRegionBaseAddress,\r
725 DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->ReservedMemoryRegionBaseAddress,\r
726 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
727 );\r
728 if (EFI_ERROR (Status)) {\r
729 return Status;\r
730 }\r
731\r
732 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
733 }\r
734\r
735 return EFI_SUCCESS;\r
736}\r
737\r
738/**\r
739 Get VTd engine number.\r
740**/\r
741UINTN\r
742GetVtdEngineNumber (\r
743 VOID\r
744 )\r
745{\r
746 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
747 UINTN VtdIndex;\r
748\r
749 VtdIndex = 0;\r
750 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
751 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
752 switch (DmarHeader->Type) {\r
753 case EFI_ACPI_DMAR_TYPE_DRHD:\r
754 VtdIndex++;\r
755 break;\r
756 default:\r
757 break;\r
758 }\r
759 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
760 }\r
761 return VtdIndex ;\r
762}\r
763\r
764/**\r
765 Parse DMAR DRHD table.\r
766\r
767 @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
768**/\r
769EFI_STATUS\r
770ParseDmarAcpiTableDrhd (\r
771 VOID\r
772 )\r
773{\r
774 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
775 EFI_STATUS Status;\r
776 UINTN VtdIndex;\r
777\r
778 mVtdUnitNumber = GetVtdEngineNumber ();\r
779 DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));\r
780 ASSERT (mVtdUnitNumber > 0);\r
781 if (mVtdUnitNumber == 0) {\r
782 return EFI_DEVICE_ERROR;\r
783 }\r
784\r
785 mVtdUnitInformation = AllocateZeroPool (sizeof(*mVtdUnitInformation) * mVtdUnitNumber);\r
786 ASSERT (mVtdUnitInformation != NULL);\r
787 if (mVtdUnitInformation == NULL) {\r
788 return EFI_OUT_OF_RESOURCES;\r
789 }\r
790\r
791 mVtdHostAddressWidthMask = LShiftU64 (1ull, mAcpiDmarTable->HostAddressWidth) - 1;\r
792\r
793 VtdIndex = 0;\r
794 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
795 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
796 switch (DmarHeader->Type) {\r
797 case EFI_ACPI_DMAR_TYPE_DRHD:\r
798 ASSERT (VtdIndex < mVtdUnitNumber);\r
799 Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
800 if (EFI_ERROR (Status)) {\r
801 return Status;\r
802 }\r
803 VtdIndex++;\r
804\r
805 break;\r
806\r
807 default:\r
808 break;\r
809 }\r
810 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
811 }\r
812 ASSERT (VtdIndex == mVtdUnitNumber);\r
813\r
814 for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {\r
815 DumpPciDeviceInfo (VtdIndex);\r
816 }\r
817 return EFI_SUCCESS ;\r
818}\r
819\r
820/**\r
821 Parse DMAR DRHD table.\r
822\r
823 @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
824**/\r
825EFI_STATUS\r
826ParseDmarAcpiTableRmrr (\r
827 VOID\r
828 )\r
829{\r
830 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
831 EFI_STATUS Status;\r
832\r
833 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
834 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
835 switch (DmarHeader->Type) {\r
836 case EFI_ACPI_DMAR_TYPE_RMRR:\r
837 Status = ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
838 if (EFI_ERROR (Status)) {\r
839 return Status;\r
840 }\r
841 break;\r
842 default:\r
843 break;\r
844 }\r
845 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
846 }\r
847 return EFI_SUCCESS ;\r
848}\r
849\r
850/**\r
851 This function scan ACPI table in RSDT.\r
852\r
853 @param[in] Rsdt ACPI RSDT\r
854 @param[in] Signature ACPI table signature\r
855\r
856 @return ACPI table\r
857**/\r
858VOID *\r
859ScanTableInRSDT (\r
860 IN RSDT_TABLE *Rsdt,\r
861 IN UINT32 Signature\r
862 )\r
863{\r
864 UINTN Index;\r
865 UINT32 EntryCount;\r
866 UINT32 *EntryPtr;\r
867 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
868\r
869 EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);\r
870\r
871 EntryPtr = &Rsdt->Entry;\r
872 for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) {\r
873 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr));\r
874 if (Table->Signature == Signature) {\r
875 return Table;\r
876 }\r
877 }\r
878\r
879 return NULL;\r
880}\r
881\r
882/**\r
883 This function scan ACPI table in XSDT.\r
884\r
885 @param[in] Xsdt ACPI XSDT\r
886 @param[in] Signature ACPI table signature\r
887\r
888 @return ACPI table\r
889**/\r
890VOID *\r
891ScanTableInXSDT (\r
892 IN XSDT_TABLE *Xsdt,\r
893 IN UINT32 Signature\r
894 )\r
895{\r
896 UINTN Index;\r
897 UINT32 EntryCount;\r
898 UINT64 EntryPtr;\r
899 UINTN BasePtr;\r
900 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
901\r
902 EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);\r
903\r
904 BasePtr = (UINTN)(&(Xsdt->Entry));\r
905 for (Index = 0; Index < EntryCount; Index ++) {\r
906 CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64));\r
907 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr));\r
908 if (Table->Signature == Signature) {\r
909 return Table;\r
910 }\r
911 }\r
912\r
913 return NULL;\r
914}\r
915\r
916/**\r
917 This function scan ACPI table in RSDP.\r
918\r
919 @param[in] Rsdp ACPI RSDP\r
920 @param[in] Signature ACPI table signature\r
921\r
922 @return ACPI table\r
923**/\r
924VOID *\r
925FindAcpiPtr (\r
926 IN EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp,\r
927 IN UINT32 Signature\r
928 )\r
929{\r
930 EFI_ACPI_DESCRIPTION_HEADER *AcpiTable;\r
931 RSDT_TABLE *Rsdt;\r
932 XSDT_TABLE *Xsdt;\r
933\r
934 AcpiTable = NULL;\r
935\r
936 //\r
937 // Check ACPI2.0 table\r
938 //\r
939 Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;\r
940 Xsdt = NULL;\r
941 if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) {\r
942 Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress;\r
943 }\r
944 //\r
945 // Check Xsdt\r
946 //\r
947 if (Xsdt != NULL) {\r
948 AcpiTable = ScanTableInXSDT (Xsdt, Signature);\r
949 }\r
950 //\r
951 // Check Rsdt\r
952 //\r
953 if ((AcpiTable == NULL) && (Rsdt != NULL)) {\r
954 AcpiTable = ScanTableInRSDT (Rsdt, Signature);\r
955 }\r
956\r
957 return AcpiTable;\r
958}\r
959\r
960/**\r
961 Get the DMAR ACPI table.\r
962\r
963 @retval EFI_SUCCESS The DMAR ACPI table is got.\r
964 @retval EFI_NOT_FOUND The DMAR ACPI table is not found.\r
965**/\r
966EFI_STATUS\r
967GetDmarAcpiTable (\r
968 VOID\r
969 )\r
970{\r
971 VOID *AcpiTable;\r
972 EFI_STATUS Status;\r
973\r
974 AcpiTable = NULL;\r
975 Status = EfiGetSystemConfigurationTable (\r
976 &gEfiAcpi20TableGuid,\r
977 &AcpiTable\r
978 );\r
979 if (EFI_ERROR (Status)) {\r
980 Status = EfiGetSystemConfigurationTable (\r
981 &gEfiAcpiTableGuid,\r
982 &AcpiTable\r
983 );\r
984 }\r
985 ASSERT (AcpiTable != NULL);\r
986\r
987 mAcpiDmarTable = FindAcpiPtr (\r
988 (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiTable,\r
989 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE\r
990 );\r
991 DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));\r
992 if (mAcpiDmarTable == NULL) {\r
993 return EFI_UNSUPPORTED;\r
994 }\r
995 VtdDumpDmarTable();\r
996\r
997 return EFI_SUCCESS;\r
998}\r