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