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