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