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