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