]> git.proxmox.com Git - mirror_edk2.git/blame - IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
IntelSiliconPkg IntelVTdDxe: Fix potential NULL pointer dereference
[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
c049fc99
JY
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
0bc94c74 30EFI_ACPI_DMAR_HEADER *mAcpiDmarTable = NULL;\r
c049fc99
JY
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
f77d35c7
JY
52 ));\r
53 DEBUG ((DEBUG_INFO,\r
c049fc99 54 " * DMA-Remapping Device Scope Entry Structure *\n"\r
f77d35c7
JY
55 ));\r
56 DEBUG ((DEBUG_INFO,\r
c049fc99
JY
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
f77d35c7
JY
147 ));\r
148 DEBUG ((DEBUG_INFO,\r
c049fc99 149 " * ACPI Name-space Device Declaration Structure *\n"\r
f77d35c7
JY
150 ));\r
151 DEBUG ((DEBUG_INFO,\r
c049fc99
JY
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
f77d35c7
JY
200 ));\r
201 DEBUG ((DEBUG_INFO,\r
c049fc99 202 " * Remapping Hardware Status Affinity Structure *\n"\r
f77d35c7
JY
203 ));\r
204 DEBUG ((DEBUG_INFO,\r
c049fc99
JY
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
f77d35c7
JY
256 ));\r
257 DEBUG ((DEBUG_INFO,\r
c049fc99 258 " * Root Port ATS Capability Reporting Structure *\n"\r
f77d35c7
JY
259 ));\r
260 DEBUG ((DEBUG_INFO,\r
c049fc99
JY
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
f77d35c7
JY
324 ));\r
325 DEBUG ((DEBUG_INFO,\r
c049fc99 326 " * Reserved Memory Region Reporting Structure *\n"\r
f77d35c7
JY
327 ));\r
328 DEBUG ((DEBUG_INFO,\r
c049fc99
JY
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
f77d35c7
JY
392 ));\r
393 DEBUG ((DEBUG_INFO,\r
c049fc99 394 " * DMA-Remapping Hardware Definition Structure *\n"\r
f77d35c7
JY
395 ));\r
396 DEBUG ((DEBUG_INFO,\r
c049fc99
JY
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
f77d35c7
JY
467 ));\r
468 DEBUG ((DEBUG_INFO,\r
c049fc99 469 "* DMAR Table *\n"\r
f77d35c7
JY
470 ));\r
471 DEBUG ((DEBUG_INFO,\r
c049fc99
JY
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\r
502 DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);\r
503 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);\r
504 while (DmarLen > 0) {\r
505 switch (DmarHeader->Type) {\r
506 case EFI_ACPI_DMAR_TYPE_DRHD:\r
507 DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
508 break;\r
509 case EFI_ACPI_DMAR_TYPE_RMRR:\r
510 DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
511 break;\r
512 case EFI_ACPI_DMAR_TYPE_ATSR:\r
513 DumpDmarAtsr ((EFI_ACPI_DMAR_ATSR_HEADER *)DmarHeader);\r
514 break;\r
515 case EFI_ACPI_DMAR_TYPE_RHSA:\r
516 DumpDmarRhsa ((EFI_ACPI_DMAR_RHSA_HEADER *)DmarHeader);\r
517 break;\r
518 case EFI_ACPI_DMAR_TYPE_ANDD:\r
519 DumpDmarAndd ((EFI_ACPI_DMAR_ANDD_HEADER *)DmarHeader);\r
520 break;\r
521 default:\r
522 break;\r
523 }\r
524 DmarLen -= DmarHeader->Length;\r
525 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
526 }\r
527\r
528 DEBUG ((DEBUG_INFO,\r
529 "*****************************************************************************\n\n"\r
530 ));\r
531\r
532 return;\r
533}\r
534\r
535/**\r
536 Dump DMAR ACPI table.\r
537**/\r
538VOID\r
539VtdDumpDmarTable (\r
540 VOID\r
541 )\r
542{\r
543 DumpAcpiDMAR ((EFI_ACPI_DMAR_HEADER *)(UINTN)mAcpiDmarTable);\r
544}\r
545\r
546/**\r
547 Get PCI device information from DMAR DevScopeEntry.\r
548\r
549 @param[in] Segment The segment number.\r
550 @param[in] DmarDevScopeEntry DMAR DevScopeEntry\r
551 @param[out] Bus The bus number.\r
552 @param[out] Device The device number.\r
553 @param[out] Function The function number.\r
554\r
555 @retval EFI_SUCCESS The PCI device information is returned.\r
556**/\r
557EFI_STATUS\r
558GetPciBusDeviceFunction (\r
559 IN UINT16 Segment,\r
560 IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,\r
561 OUT UINT8 *Bus,\r
562 OUT UINT8 *Device,\r
563 OUT UINT8 *Function\r
564 )\r
565{\r
566 EFI_ACPI_DMAR_PCI_PATH *DmarPciPath;\r
567 UINT8 MyBus;\r
568 UINT8 MyDevice;\r
569 UINT8 MyFunction;\r
570\r
571 DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *)((UINTN)(DmarDevScopeEntry + 1));\r
572 MyBus = DmarDevScopeEntry->StartBusNumber;\r
573 MyDevice = DmarPciPath->Device;\r
574 MyFunction = DmarPciPath->Function;\r
575\r
576 switch (DmarDevScopeEntry->Type) {\r
577 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
578 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
f77d35c7 579 while ((UINTN)DmarPciPath + sizeof(EFI_ACPI_DMAR_PCI_PATH) < (UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length) {\r
c049fc99 580 MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
f77d35c7 581 DmarPciPath ++;\r
c049fc99
JY
582 MyDevice = DmarPciPath->Device;\r
583 MyFunction = DmarPciPath->Function;\r
c049fc99
JY
584 }\r
585 break;\r
586 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
587 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
588 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
589 break;\r
590 }\r
591\r
592 *Bus = MyBus;\r
593 *Device = MyDevice;\r
594 *Function = MyFunction;\r
595\r
596 return EFI_SUCCESS;\r
597}\r
598\r
599/**\r
600 Process DMAR DHRD table.\r
601\r
602 @param[in] VtdIndex The index of VTd engine.\r
603 @param[in] DmarDrhd The DRHD table.\r
604\r
605 @retval EFI_SUCCESS The DRHD table is processed.\r
606**/\r
607EFI_STATUS\r
608ProcessDhrd (\r
609 IN UINTN VtdIndex,\r
610 IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd\r
611 )\r
612{\r
613 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
614 UINT8 Bus;\r
615 UINT8 Device;\r
616 UINT8 Function;\r
617 UINT8 SecondaryBusNumber;\r
618 EFI_STATUS Status;\r
619 VTD_SOURCE_ID SourceId;\r
c049fc99
JY
620\r
621 mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress = (UINTN)DmarDrhd->RegisterBaseAddress;\r
622 DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));\r
623\r
624 mVtdUnitInformation[VtdIndex].Segment = DmarDrhd->SegmentNumber;\r
625\r
626 if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {\r
627 mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE;\r
628 DEBUG ((DEBUG_INFO," ProcessDhrd: with INCLUDE ALL\n"));\r
629\r
f77d35c7 630 Status = ScanPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, 0, ScanBusCallbackRegisterPciDevice);\r
c049fc99
JY
631 if (EFI_ERROR (Status)) {\r
632 return Status;\r
633 }\r
634 } else {\r
635 mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE;\r
636 DEBUG ((DEBUG_INFO," ProcessDhrd: without INCLUDE ALL\n"));\r
637 }\r
638\r
639 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));\r
640 while ((UINTN)DmarDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {\r
641\r
642 Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);\r
643 if (EFI_ERROR (Status)) {\r
644 return Status;\r
645 }\r
c049fc99
JY
646\r
647 DEBUG ((DEBUG_INFO," ProcessDhrd: "));\r
648 switch (DmarDevScopeEntry->Type) {\r
649 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
650 DEBUG ((DEBUG_INFO,"PCI Endpoint"));\r
651 break;\r
652 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
653 DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));\r
654 break;\r
655 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:\r
656 DEBUG ((DEBUG_INFO,"IOAPIC"));\r
657 break;\r
658 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:\r
659 DEBUG ((DEBUG_INFO,"MSI Capable HPET"));\r
660 break;\r
661 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:\r
662 DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));\r
663 break;\r
664 }\r
665 DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumber, Bus, Device, Function));\r
666\r
667 SourceId.Bits.Bus = Bus;\r
668 SourceId.Bits.Device = Device;\r
669 SourceId.Bits.Function = Function;\r
670\r
f77d35c7 671 Status = RegisterPciDevice (VtdIndex, DmarDrhd->SegmentNumber, SourceId, DmarDevScopeEntry->Type, TRUE);\r
c049fc99
JY
672 if (EFI_ERROR (Status)) {\r
673 //\r
674 // There might be duplication for special device other than standard PCI device.\r
675 //\r
676 switch (DmarDevScopeEntry->Type) {\r
677 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:\r
678 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
679 return Status;\r
680 }\r
681 }\r
682\r
683 switch (DmarDevScopeEntry->Type) {\r
684 case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:\r
685 SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DmarDrhd->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
f77d35c7 686 Status = ScanPciBus ((VOID *)VtdIndex, DmarDrhd->SegmentNumber, SecondaryBusNumber, ScanBusCallbackRegisterPciDevice);\r
c049fc99
JY
687 if (EFI_ERROR (Status)) {\r
688 return Status;\r
689 }\r
690 break;\r
691 default:\r
692 break;\r
693 }\r
694\r
695 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
696 }\r
697\r
698 return EFI_SUCCESS;\r
699}\r
700\r
701/**\r
702 Process DMAR RMRR table.\r
703\r
704 @param[in] DmarRmrr The RMRR table.\r
705\r
706 @retval EFI_SUCCESS The RMRR table is processed.\r
707**/\r
708EFI_STATUS\r
709ProcessRmrr (\r
710 IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr\r
711 )\r
712{\r
713 EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;\r
714 UINT8 Bus;\r
715 UINT8 Device;\r
716 UINT8 Function;\r
717 EFI_STATUS Status;\r
718 VTD_SOURCE_ID SourceId;\r
719\r
720 DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));\r
721\r
722 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));\r
723 while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {\r
724 if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) {\r
725 DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%x] \n", DmarDevScopeEntry->Type));\r
726 return EFI_DEVICE_ERROR;\r
727 }\r
728\r
729 Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);\r
730 if (EFI_ERROR (Status)) {\r
731 return Status;\r
732 }\r
733\r
734 DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function));\r
735\r
736 SourceId.Bits.Bus = Bus;\r
737 SourceId.Bits.Device = Device;\r
738 SourceId.Bits.Function = Function;\r
739 Status = SetAccessAttribute (\r
740 DmarRmrr->SegmentNumber,\r
741 SourceId,\r
742 DmarRmrr->ReservedMemoryRegionBaseAddress,\r
743 DmarRmrr->ReservedMemoryRegionLimitAddress + 1 - DmarRmrr->ReservedMemoryRegionBaseAddress,\r
744 EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
745 );\r
746 if (EFI_ERROR (Status)) {\r
747 return Status;\r
748 }\r
749\r
750 DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);\r
751 }\r
752\r
753 return EFI_SUCCESS;\r
754}\r
755\r
756/**\r
757 Get VTd engine number.\r
758**/\r
759UINTN\r
760GetVtdEngineNumber (\r
761 VOID\r
762 )\r
763{\r
764 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
765 UINTN VtdIndex;\r
766\r
767 VtdIndex = 0;\r
768 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
769 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
770 switch (DmarHeader->Type) {\r
771 case EFI_ACPI_DMAR_TYPE_DRHD:\r
772 VtdIndex++;\r
773 break;\r
774 default:\r
775 break;\r
776 }\r
777 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
778 }\r
779 return VtdIndex ;\r
780}\r
781\r
782/**\r
783 Parse DMAR DRHD table.\r
784\r
785 @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
786**/\r
787EFI_STATUS\r
788ParseDmarAcpiTableDrhd (\r
789 VOID\r
790 )\r
791{\r
792 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
793 EFI_STATUS Status;\r
794 UINTN VtdIndex;\r
795\r
796 mVtdUnitNumber = GetVtdEngineNumber ();\r
797 DEBUG ((DEBUG_INFO," VtdUnitNumber - %d\n", mVtdUnitNumber));\r
798 ASSERT (mVtdUnitNumber > 0);\r
799 if (mVtdUnitNumber == 0) {\r
800 return EFI_DEVICE_ERROR;\r
801 }\r
802\r
803 mVtdUnitInformation = AllocateZeroPool (sizeof(*mVtdUnitInformation) * mVtdUnitNumber);\r
804 ASSERT (mVtdUnitInformation != NULL);\r
805 if (mVtdUnitInformation == NULL) {\r
806 return EFI_OUT_OF_RESOURCES;\r
807 }\r
808\r
809 mVtdHostAddressWidthMask = LShiftU64 (1ull, mAcpiDmarTable->HostAddressWidth) - 1;\r
810\r
811 VtdIndex = 0;\r
812 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
813 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
814 switch (DmarHeader->Type) {\r
815 case EFI_ACPI_DMAR_TYPE_DRHD:\r
816 ASSERT (VtdIndex < mVtdUnitNumber);\r
817 Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);\r
818 if (EFI_ERROR (Status)) {\r
819 return Status;\r
820 }\r
821 VtdIndex++;\r
822\r
823 break;\r
824\r
825 default:\r
826 break;\r
827 }\r
828 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
829 }\r
830 ASSERT (VtdIndex == mVtdUnitNumber);\r
831\r
832 for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {\r
833 DumpPciDeviceInfo (VtdIndex);\r
834 }\r
835 return EFI_SUCCESS ;\r
836}\r
837\r
838/**\r
839 Parse DMAR DRHD table.\r
840\r
841 @return EFI_SUCCESS The DMAR DRHD table is parsed.\r
842**/\r
843EFI_STATUS\r
844ParseDmarAcpiTableRmrr (\r
845 VOID\r
846 )\r
847{\r
848 EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;\r
849 EFI_STATUS Status;\r
850\r
851 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));\r
852 while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {\r
853 switch (DmarHeader->Type) {\r
854 case EFI_ACPI_DMAR_TYPE_RMRR:\r
855 Status = ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);\r
856 if (EFI_ERROR (Status)) {\r
857 return Status;\r
858 }\r
859 break;\r
860 default:\r
861 break;\r
862 }\r
863 DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);\r
864 }\r
865 return EFI_SUCCESS ;\r
866}\r
867\r
868/**\r
869 This function scan ACPI table in RSDT.\r
870\r
871 @param[in] Rsdt ACPI RSDT\r
872 @param[in] Signature ACPI table signature\r
873\r
874 @return ACPI table\r
875**/\r
876VOID *\r
877ScanTableInRSDT (\r
878 IN RSDT_TABLE *Rsdt,\r
879 IN UINT32 Signature\r
880 )\r
881{\r
882 UINTN Index;\r
883 UINT32 EntryCount;\r
884 UINT32 *EntryPtr;\r
885 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
886\r
887 EntryCount = (Rsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32);\r
888\r
889 EntryPtr = &Rsdt->Entry;\r
890 for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) {\r
891 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(*EntryPtr));\r
01bd1c98 892 if ((Table != NULL) && (Table->Signature == Signature)) {\r
c049fc99
JY
893 return Table;\r
894 }\r
895 }\r
896\r
897 return NULL;\r
898}\r
899\r
900/**\r
901 This function scan ACPI table in XSDT.\r
902\r
903 @param[in] Xsdt ACPI XSDT\r
904 @param[in] Signature ACPI table signature\r
905\r
906 @return ACPI table\r
907**/\r
908VOID *\r
909ScanTableInXSDT (\r
910 IN XSDT_TABLE *Xsdt,\r
911 IN UINT32 Signature\r
912 )\r
913{\r
914 UINTN Index;\r
915 UINT32 EntryCount;\r
916 UINT64 EntryPtr;\r
917 UINTN BasePtr;\r
918 EFI_ACPI_DESCRIPTION_HEADER *Table;\r
919\r
920 EntryCount = (Xsdt->Header.Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64);\r
921\r
922 BasePtr = (UINTN)(&(Xsdt->Entry));\r
923 for (Index = 0; Index < EntryCount; Index ++) {\r
924 CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64));\r
925 Table = (EFI_ACPI_DESCRIPTION_HEADER*)((UINTN)(EntryPtr));\r
01bd1c98 926 if ((Table != NULL) && (Table->Signature == Signature)) {\r
c049fc99
JY
927 return Table;\r
928 }\r
929 }\r
930\r
931 return NULL;\r
932}\r
933\r
934/**\r
935 This function scan ACPI table in RSDP.\r
936\r
937 @param[in] Rsdp ACPI RSDP\r
938 @param[in] Signature ACPI table signature\r
939\r
940 @return ACPI table\r
941**/\r
942VOID *\r
943FindAcpiPtr (\r
944 IN EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp,\r
945 IN UINT32 Signature\r
946 )\r
947{\r
948 EFI_ACPI_DESCRIPTION_HEADER *AcpiTable;\r
949 RSDT_TABLE *Rsdt;\r
950 XSDT_TABLE *Xsdt;\r
951\r
952 AcpiTable = NULL;\r
953\r
954 //\r
955 // Check ACPI2.0 table\r
956 //\r
957 Rsdt = (RSDT_TABLE *)(UINTN)Rsdp->RsdtAddress;\r
958 Xsdt = NULL;\r
959 if ((Rsdp->Revision >= 2) && (Rsdp->XsdtAddress < (UINT64)(UINTN)-1)) {\r
960 Xsdt = (XSDT_TABLE *)(UINTN)Rsdp->XsdtAddress;\r
961 }\r
962 //\r
963 // Check Xsdt\r
964 //\r
965 if (Xsdt != NULL) {\r
966 AcpiTable = ScanTableInXSDT (Xsdt, Signature);\r
967 }\r
968 //\r
969 // Check Rsdt\r
970 //\r
971 if ((AcpiTable == NULL) && (Rsdt != NULL)) {\r
972 AcpiTable = ScanTableInRSDT (Rsdt, Signature);\r
973 }\r
974\r
975 return AcpiTable;\r
976}\r
977\r
978/**\r
979 Get the DMAR ACPI table.\r
980\r
7729e3c4
SZ
981 @retval EFI_SUCCESS The DMAR ACPI table is got.\r
982 @retval EFI_ALREADY_STARTED The DMAR ACPI table has been got previously.\r
983 @retval EFI_NOT_FOUND The DMAR ACPI table is not found.\r
c049fc99
JY
984**/\r
985EFI_STATUS\r
986GetDmarAcpiTable (\r
987 VOID\r
988 )\r
989{\r
990 VOID *AcpiTable;\r
991 EFI_STATUS Status;\r
992\r
f6f486e7 993 if (mAcpiDmarTable != NULL) {\r
7729e3c4 994 return EFI_ALREADY_STARTED;\r
f6f486e7
SZ
995 }\r
996\r
c049fc99
JY
997 AcpiTable = NULL;\r
998 Status = EfiGetSystemConfigurationTable (\r
999 &gEfiAcpi20TableGuid,\r
1000 &AcpiTable\r
1001 );\r
1002 if (EFI_ERROR (Status)) {\r
1003 Status = EfiGetSystemConfigurationTable (\r
118f1657 1004 &gEfiAcpi10TableGuid,\r
c049fc99
JY
1005 &AcpiTable\r
1006 );\r
1007 }\r
dcd39e09
SZ
1008 if (EFI_ERROR (Status)) {\r
1009 return EFI_NOT_FOUND;\r
1010 }\r
c049fc99
JY
1011 ASSERT (AcpiTable != NULL);\r
1012\r
1013 mAcpiDmarTable = FindAcpiPtr (\r
1014 (EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiTable,\r
1015 EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE\r
1016 );\r
c049fc99 1017 if (mAcpiDmarTable == NULL) {\r
f6f486e7 1018 return EFI_NOT_FOUND;\r
c049fc99 1019 }\r
f6f486e7 1020 DEBUG ((DEBUG_INFO,"DMAR Table - 0x%08x\n", mAcpiDmarTable));\r
c049fc99
JY
1021 VtdDumpDmarTable();\r
1022\r
1023 return EFI_SUCCESS;\r
1024}\r