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