TianoCore EDK2 master
Loading...
Searching...
No Matches
SsdtPcieGenerator.c
Go to the documentation of this file.
1
18#include <Library/AcpiLib.h>
19#include <Library/BaseLib.h>
21#include <Library/DebugLib.h>
23#include <Protocol/AcpiTable.h>
24
25// Module specific include files.
26#include <AcpiTableGenerator.h>
34
35#include "SsdtPcieGenerator.h"
36
37#define PCI_MAX_DEVICE_COUNT_PER_BUS 32
38#define PCI_MAX_FUNCTION_COUNT_PER_DEVICE 8
39
58 );
59
67 );
68
76 );
77
85 );
86
99EFIAPI
102 IN UINT32 Count
103 )
104{
105 UINT32 *Table;
106
107 if ((MappingTable == NULL) ||
108 (Count == 0))
109 {
110 ASSERT (0);
111 return EFI_INVALID_PARAMETER;
112 }
113
114 Table = AllocateZeroPool (sizeof (*Table) * Count);
115 if (Table == NULL) {
116 ASSERT (0);
117 return EFI_OUT_OF_RESOURCES;
118 }
119
120 MappingTable->Table = Table;
122 MappingTable->MaxIndex = Count;
123
124 return EFI_SUCCESS;
125}
126
131STATIC
132VOID
133EFIAPI
136 )
137{
138 ASSERT (MappingTable != NULL);
139 ASSERT (MappingTable->Table != NULL);
140
141 if (MappingTable->Table != NULL) {
143 }
144}
145
156STATIC
157UINT32
158EFIAPI
161 IN UINT32 Integer
162 )
163{
164 UINT32 *Table;
165 UINT32 Index;
166 UINT32 LastIndex;
167
168 ASSERT (MappingTable != NULL);
169 ASSERT (MappingTable->Table != NULL);
170
171 Table = MappingTable->Table;
172 LastIndex = MappingTable->LastIndex;
173
174 // Search if there is already an entry with this Integer.
175 for (Index = 0; Index < LastIndex; Index++) {
176 if (Table[Index] == Integer) {
177 return Index;
178 }
179 }
180
181 ASSERT (LastIndex < MappingTable->MaxIndex);
182
183 // If no, create a new entry.
184 Table[LastIndex] = Integer;
185
186 return MappingTable->LastIndex++;
187}
188
207STATIC
209EFIAPI
212 IN UINT32 Uid,
214 )
215{
216 EFI_STATUS Status;
217 UINT32 EisaId;
218
219 ASSERT (PciInfo != NULL);
220 ASSERT (PciNode != NULL);
221
222 // ASL: Name (_UID, <Uid>)
223 Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL);
224 if (EFI_ERROR (Status)) {
225 ASSERT (0);
226 return Status;
227 }
228
229 // ASL: Name (_HID, EISAID ("PNP0A08"))
230 Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
231 if (EFI_ERROR (Status)) {
232 ASSERT (0);
233 return Status;
234 }
235
236 Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
237 if (EFI_ERROR (Status)) {
238 ASSERT (0);
239 return Status;
240 }
241
242 // ASL: Name (_CID, EISAID ("PNP0A03"))
243 Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
244 if (EFI_ERROR (Status)) {
245 ASSERT (0);
246 return Status;
247 }
248
249 Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
250 if (EFI_ERROR (Status)) {
251 ASSERT (0);
252 return Status;
253 }
254
255 // ASL: Name (_SEG, <Pci segment group>)
256 Status = AmlCodeGenNameInteger (
257 "_SEG",
258 PciInfo->PciSegmentGroupNumber,
259 PciNode,
260 NULL
261 );
262 if (EFI_ERROR (Status)) {
263 ASSERT (0);
264 return Status;
265 }
266
267 // ASL: Name (_BBN, <Bus number>)
268 Status = AmlCodeGenNameInteger (
269 "_BBN",
270 PciInfo->StartBusNumber,
271 PciNode,
272 NULL
273 );
274 if (EFI_ERROR (Status)) {
275 ASSERT (0);
276 return Status;
277 }
278
279 // ASL: Name (_CCA, 1)
280 // Must be aligned with the IORT CCA property in
281 // "Table 14 Memory access properties"
282 Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);
283 ASSERT_EFI_ERROR (Status);
284 return Status;
285}
286
302STATIC
304EFIAPI
309 IN UINT32 Uid,
311 )
312{
313 EFI_STATUS Status;
314 UINT32 Index;
316 CM_ARCH_COMMON_OBJ_REF *RefInfo;
317 UINT32 RefCount;
319
320 ASSERT (Generator != NULL);
321 ASSERT (CfgMgrProtocol != NULL);
322 ASSERT (PciInfo != NULL);
323 ASSERT (PciNode != NULL);
324
325 PrtNode = NULL;
326
327 // Get the array of CM_ARCH_COMMON_OBJ_REF referencing the
328 // CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO objects.
329 Status = GetEArchCommonObjCmRef (
330 CfgMgrProtocol,
331 PciInfo->InterruptMapToken,
332 &RefInfo,
333 &RefCount
334 );
335 if (EFI_ERROR (Status)) {
336 ASSERT (0);
337 return Status;
338 }
339
340 // Initialized DeviceTable.
341 Status = MappingTableInitialize (&Generator->DeviceTable, RefCount);
342 if (EFI_ERROR (Status)) {
343 ASSERT (0);
344 goto exit_handler0;
345 }
346
347 // ASL: Name (_PRT, Package () {})
348 Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode);
349 if (EFI_ERROR (Status)) {
350 ASSERT (0);
351 goto exit_handler;
352 }
353
354 for (Index = 0; Index < RefCount; Index++) {
355 // Get CM_ARCH_COMMON_PCI_INTERRUPT_MAP_INFO structures one by one.
356 Status = GetEArchCommonObjPciInterruptMapInfo (
357 CfgMgrProtocol,
358 RefInfo[Index].ReferenceToken,
359 &IrqMapInfo,
360 NULL
361 );
362 if (EFI_ERROR (Status)) {
363 ASSERT (0);
364 goto exit_handler;
365 }
366
367 // Check that the interrupts flags are SPIs, level high.
368 // Cf. Arm BSA v1.0, sE.6 "Legacy interrupts"
369 if ((Index > 0) &&
370 (IrqMapInfo->IntcInterrupt.Interrupt >= 32) &&
371 (IrqMapInfo->IntcInterrupt.Interrupt < 1020) &&
372 ((IrqMapInfo->IntcInterrupt.Flags & 0xB) != 0))
373 {
374 Status = EFI_INVALID_PARAMETER;
375 ASSERT_EFI_ERROR (Status);
376 goto exit_handler;
377 }
378
379 // Add the device to the DeviceTable.
380 MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice);
381
382 /* Add a _PRT entry.
383 ASL
384 Name (_PRT, Package () {
385 <OldPrtEntries>,
386 <NewPrtEntry>
387 })
388
389 Address is set as:
390 ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
391 High word-Device #, Low word-Function #. (for example, device 3,
392 function 2 is 0x00030002). To refer to all the functions on a device #,
393 use a function number of FFFF).
394
395 Use the second model for _PRT object and describe a hardwired interrupt.
396 */
397 Status = AmlAddPrtEntry (
398 (IrqMapInfo->PciDevice << 16) | 0xFFFF,
399 IrqMapInfo->PciInterrupt,
400 NULL,
401 IrqMapInfo->IntcInterrupt.Interrupt,
402 PrtNode
403 );
404 if (EFI_ERROR (Status)) {
405 ASSERT (0);
406 goto exit_handler;
407 }
408 } // for
409
410 // Attach the _PRT entry.
411 Status = AmlAttachNode (PciNode, PrtNode);
412 if (EFI_ERROR (Status)) {
413 ASSERT_EFI_ERROR (Status);
414 goto exit_handler;
415 }
416
417 PrtNode = NULL;
418
419 // Generate the Pci slots once all the device have been added.
420 Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, Uid, PciNode);
421 if (EFI_ERROR (Status)) {
422 ASSERT (0);
423 goto exit_handler;
424 }
425
426exit_handler:
427 MappingTableFree (&Generator->DeviceTable);
428exit_handler0:
429 if (PrtNode != NULL) {
430 AmlDeleteTree (PrtNode);
431 }
432
433 return Status;
434}
435
448STATIC
450EFIAPI
456 )
457{
458 EFI_STATUS Status;
459 BOOLEAN Translation;
460 UINT32 Index;
461 CM_ARCH_COMMON_OBJ_REF *RefInfo;
462 UINT32 RefCount;
465 BOOLEAN IsPosDecode;
466
467 ASSERT (Generator != NULL);
468 ASSERT (CfgMgrProtocol != NULL);
469 ASSERT (PciInfo != NULL);
470 ASSERT (PciNode != NULL);
471
472 // ASL: Name (_CRS, ResourceTemplate () {})
473 Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);
474 if (EFI_ERROR (Status)) {
475 ASSERT (0);
476 return Status;
477 }
478
479 // ASL:
480 // WordBusNumber ( // Bus numbers assigned to this root
481 // ResourceProducer, MinFixed, MaxFixed, PosDecode,
482 // 0, // AddressGranularity
483 // <Start>, // AddressMinimum - Minimum Bus Number
484 // <End>, // AddressMaximum - Maximum Bus Number
485 // 0, // AddressTranslation - Set to 0
486 // <End> - <Start> + 1 // RangeLength - Number of Busses
487 // )
489 FALSE,
490 TRUE,
491 TRUE,
492 TRUE,
493 0,
494 PciInfo->StartBusNumber,
495 PciInfo->EndBusNumber,
496 0,
497 PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1,
498 0,
499 NULL,
500 CrsNode,
501 NULL
502 );
503 if (EFI_ERROR (Status)) {
504 ASSERT (0);
505 return Status;
506 }
507
508 // Get the array of CM_ARCH_COMMON_OBJ_REF referencing the
509 // CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO objects.
510 Status = GetEArchCommonObjCmRef (
511 CfgMgrProtocol,
512 PciInfo->AddressMapToken,
513 &RefInfo,
514 &RefCount
515 );
516 if (EFI_ERROR (Status)) {
517 ASSERT (0);
518 return Status;
519 }
520
521 for (Index = 0; Index < RefCount; Index++) {
522 // Get CM_ARCH_COMMON_PCI_ADDRESS_MAP_INFO structures one by one.
523 Status = GetEArchCommonObjPciAddressMapInfo (
524 CfgMgrProtocol,
525 RefInfo[Index].ReferenceToken,
526 &AddrMapInfo,
527 NULL
528 );
529 if (EFI_ERROR (Status)) {
530 ASSERT (0);
531 return Status;
532 }
533
534 Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);
535 if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) {
536 IsPosDecode = TRUE;
537 } else {
538 IsPosDecode = FALSE;
539 }
540
541 switch (AddrMapInfo->SpaceCode) {
542 case PCI_SS_IO:
543 Status = AmlCodeGenRdQWordIo (
544 FALSE,
545 TRUE,
546 TRUE,
547 IsPosDecode,
548 3,
549 0,
550 AddrMapInfo->PciAddress,
551 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
552 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,
553 AddrMapInfo->AddressSize,
554 0,
555 NULL,
556 TRUE,
557 FALSE,
558 CrsNode,
559 NULL
560 );
561 break;
562
563 case PCI_SS_M32:
564 ASSERT ((AddrMapInfo->PciAddress & ~MAX_UINT32) == 0);
565 ASSERT (((AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1) & ~MAX_UINT32) == 0);
566 ASSERT (((Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0) & ~MAX_UINT32) == 0);
567 ASSERT ((AddrMapInfo->AddressSize & ~MAX_UINT32) == 0);
568
569 Status = AmlCodeGenRdDWordMemory (
570 FALSE,
571 IsPosDecode,
572 TRUE,
573 TRUE,
574 AmlMemoryCacheable,
575 TRUE,
576 0,
577 (UINT32)(AddrMapInfo->PciAddress),
578 (UINT32)(AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1),
579 (UINT32)(Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0),
580 (UINT32)(AddrMapInfo->AddressSize),
581 0,
582 NULL,
583 AmlAddressRangeMemory,
584 TRUE,
585 CrsNode,
586 NULL
587 );
588 break;
589
590 case PCI_SS_M64:
591 Status = AmlCodeGenRdQWordMemory (
592 FALSE,
593 IsPosDecode,
594 TRUE,
595 TRUE,
596 AmlMemoryCacheable,
597 TRUE,
598 0,
599 AddrMapInfo->PciAddress,
600 AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
601 Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,
602 AddrMapInfo->AddressSize,
603 0,
604 NULL,
605 AmlAddressRangeMemory,
606 TRUE,
607 CrsNode,
608 NULL
609 );
610 break;
611
612 default:
613 Status = EFI_INVALID_PARAMETER;
614 } // switch
615
616 if (EFI_ERROR (Status)) {
617 ASSERT (0);
618 return Status;
619 }
620 } // for
621
622 return Status;
623}
624
636STATIC
638EFIAPI
642 )
643{
644 EFI_STATUS Status;
645 UINT32 EisaId;
647
648 if (CrsNode == NULL) {
649 ASSERT (0);
650 return EFI_INVALID_PARAMETER;
651 }
652
653 // ASL: Device (RES0) {}
654 Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode);
655 if (EFI_ERROR (Status)) {
656 ASSERT (0);
657 return Status;
658 }
659
660 // ASL: Name (_HID, EISAID ("PNP0C02"))
661 Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */
662 if (EFI_ERROR (Status)) {
663 ASSERT (0);
664 return Status;
665 }
666
667 Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);
668 if (EFI_ERROR (Status)) {
669 ASSERT (0);
670 return Status;
671 }
672
673 // ASL: Name (_CRS, ResourceTemplate () {})
674 Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode);
675 if (EFI_ERROR (Status)) {
676 ASSERT (0);
677 return Status;
678 }
679
680 return Status;
681}
682
695STATIC
697EFIAPI
703 )
704{
705 EFI_STATUS Status;
707 UINT64 AddressMinimum;
708 UINT64 AddressMaximum;
709
710 Status = GenerateMotherboardDevice (PciNode, &CrsNode);
711 if (EFI_ERROR (Status)) {
712 ASSERT (0);
713 return Status;
714 }
715
716 AddressMinimum = PciInfo->BaseAddress + (PciInfo->StartBusNumber *
717 PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB);
718 AddressMaximum = PciInfo->BaseAddress + ((PciInfo->EndBusNumber + 1) *
719 PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB) - 1;
720
721 Status = AmlCodeGenRdQWordMemory (
722 FALSE,
723 TRUE,
724 TRUE,
725 TRUE,
726 AmlMemoryNonCacheable,
727 TRUE,
728 0,
729 AddressMinimum,
730 AddressMaximum,
731 0, // no translation
732 AddressMaximum - AddressMinimum + 1,
733 0,
734 NULL,
735 AmlAddressRangeMemory,
736 TRUE,
737 CrsNode,
738 NULL
739 );
740
741 if (EFI_ERROR (Status)) {
742 ASSERT (0);
743 return Status;
744 }
745
746 return Status;
747}
748
762STATIC
764EFIAPI
769 IN UINT32 Uid,
770 IN OUT AML_ROOT_NODE_HANDLE *RootNode
771 )
772{
773 EFI_STATUS Status;
774
775 CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
776 AML_OBJECT_NODE_HANDLE ScopeNode;
778
779 ASSERT (Generator != NULL);
780 ASSERT (CfgMgrProtocol != NULL);
781 ASSERT (PciInfo != NULL);
782 ASSERT (RootNode != NULL);
783
784 PciNode = NULL;
785
786 // ASL: Scope (\_SB) {}
787 Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);
788 if (EFI_ERROR (Status)) {
789 ASSERT (0);
790 return Status;
791 }
792
793 // Write the name of the PCI device.
794 CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);
795 AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF);
796 if (Uid > 0xF) {
797 AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF);
798 }
799
800 // ASL: Device (PCIx) {}
801 Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);
802 if (EFI_ERROR (Status)) {
803 ASSERT (0);
804 return Status;
805 }
806
807 // Populate the PCIx node with some Id values.
808 Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode);
809 if (EFI_ERROR (Status)) {
810 ASSERT (0);
811 return Status;
812 }
813
814 // Generate the Pci Routing Table (_PRT).
815 if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) {
816 Status = GeneratePrt (
817 Generator,
818 CfgMgrProtocol,
819 PciInfo,
820 Uid,
821 PciNode
822 );
823 if (EFI_ERROR (Status)) {
824 ASSERT (0);
825 return Status;
826 }
827 }
828
829 // Generate the _CRS method.
830 Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode);
831 if (EFI_ERROR (Status)) {
832 ASSERT (0);
833 return Status;
834 }
835
836 // Add the PNP Motherboard Resources Device to reserve ECAM space
837 Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode);
838 if (EFI_ERROR (Status)) {
839 ASSERT (0);
840 return Status;
841 }
842
843 // Add the template _OSC method.
844 Status = AddOscMethod (PciInfo, PciNode);
845 ASSERT_EFI_ERROR (Status);
846
847 return Status;
848}
849
864STATIC
866EFIAPI
872 IN UINT32 Uid,
874 )
875{
876 EFI_STATUS Status;
877 EFI_STATUS Status1;
878 AML_ROOT_NODE_HANDLE RootNode;
879
880 ASSERT (Generator != NULL);
881 ASSERT (CfgMgrProtocol != NULL);
882 ASSERT (PciInfo != NULL);
883 ASSERT (Table != NULL);
884
885 // Create a new Ssdt table.
886 Status = AddSsdtAcpiHeader (
887 CfgMgrProtocol,
888 &Generator->Header,
889 AcpiTableInfo,
890 &RootNode
891 );
892 if (EFI_ERROR (Status)) {
893 ASSERT (0);
894 return Status;
895 }
896
897 Status = GeneratePciDevice (
898 Generator,
899 CfgMgrProtocol,
900 PciInfo,
901 Uid,
902 RootNode
903 );
904 if (EFI_ERROR (Status)) {
905 ASSERT (0);
906 goto exit_handler;
907 }
908
909 // Serialize the tree.
911 RootNode,
912 Table
913 );
914 if (EFI_ERROR (Status)) {
915 DEBUG ((
916 DEBUG_ERROR,
917 "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."
918 " Status = %r\n",
919 Status
920 ));
921 }
922
923exit_handler:
924 // Cleanup
925 Status1 = AmlDeleteTree (RootNode);
926 if (EFI_ERROR (Status1)) {
927 DEBUG ((
928 DEBUG_ERROR,
929 "ERROR: SSDT-PCI: Failed to cleanup AML tree."
930 " Status = %r\n",
931 Status1
932 ));
933 // If Status was success but we failed to delete the AML Tree
934 // return Status1 else return the original error code, i.e. Status.
935 if (!EFI_ERROR (Status)) {
936 return Status1;
937 }
938 }
939
940 return Status;
941}
942
968STATIC
970EFIAPI
976 OUT UINTN *CONST TableCount
977 )
978{
979 EFI_STATUS Status;
981 UINT32 PciCount;
982 UINT32 Index;
983 EFI_ACPI_DESCRIPTION_HEADER **TableList;
985 UINT32 Uid;
986
987 ASSERT (This != NULL);
988 ASSERT (AcpiTableInfo != NULL);
989 ASSERT (CfgMgrProtocol != NULL);
990 ASSERT (Table != NULL);
991 ASSERT (TableCount != NULL);
992 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
993 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
994
995 *TableCount = 0;
997
998 Status = GetEArchCommonObjPciConfigSpaceInfo (
999 CfgMgrProtocol,
1001 &PciInfo,
1002 &PciCount
1003 );
1004 if (EFI_ERROR (Status)) {
1005 ASSERT (0);
1006 return Status;
1007 }
1008
1009 if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {
1010 DEBUG ((
1011 DEBUG_ERROR,
1012 "ERROR: SSDT-PCI: Too many Pci root complexes: %d."
1013 " Maximum Pci root complexes supported = %d.\n",
1014 PciCount,
1016 ));
1017 return EFI_INVALID_PARAMETER;
1018 }
1019
1020 // Allocate a table to store pointers to the SSDT tables.
1021 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)
1023 (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * PciCount)
1024 );
1025 if (TableList == NULL) {
1026 Status = EFI_OUT_OF_RESOURCES;
1027 DEBUG ((
1028 DEBUG_ERROR,
1029 "ERROR: SSDT-PCI: Failed to allocate memory for Table List."
1030 " Status = %r\n",
1031 Status
1032 ));
1033 return Status;
1034 }
1035
1036 // Setup the table list early so that appropriate cleanup
1037 // can be done in case of failure.
1038 *Table = TableList;
1039
1040 for (Index = 0; Index < PciCount; Index++) {
1041 if (PcdGetBool (PcdPciUseSegmentAsUid)) {
1042 Uid = PciInfo[Index].PciSegmentGroupNumber;
1044 DEBUG ((
1045 DEBUG_ERROR,
1046 "ERROR: SSDT-PCI: Pci root complexes segment number: %d."
1047 " Greater than maximum number of Pci root complexes supported = %d.\n",
1048 Uid,
1050 ));
1051 return EFI_INVALID_PARAMETER;
1052 }
1053 } else {
1054 Uid = Index;
1055 }
1056
1057 // Build a SSDT table describing the Pci devices.
1058 Status = BuildSsdtPciTable (
1059 Generator,
1060 CfgMgrProtocol,
1061 AcpiTableInfo,
1062 &PciInfo[Index],
1063 Uid,
1064 &TableList[Index]
1065 );
1066 if (EFI_ERROR (Status)) {
1067 DEBUG ((
1068 DEBUG_ERROR,
1069 "ERROR: SSDT-PCI: Failed to build associated SSDT table."
1070 " Status = %r\n",
1071 Status
1072 ));
1073 goto error_handler;
1074 }
1075
1076 *TableCount += 1;
1077 } // for
1078
1079error_handler:
1080 // Note: Table list and Table count have been setup. The
1081 // error handler does nothing here as the framework will invoke
1082 // FreeSsdtPciTableEx () even on failure.
1083 return Status;
1084}
1085
1099STATIC
1101EFIAPI
1107 IN CONST UINTN TableCount
1108 )
1109{
1110 EFI_ACPI_DESCRIPTION_HEADER **TableList;
1111 UINTN Index;
1112
1113 ASSERT (This != NULL);
1114 ASSERT (AcpiTableInfo != NULL);
1115 ASSERT (CfgMgrProtocol != NULL);
1116 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
1117 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
1118
1119 if ((Table == NULL) ||
1120 (*Table == NULL) ||
1121 (TableCount == 0))
1122 {
1123 DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n"));
1124 return EFI_INVALID_PARAMETER;
1125 }
1126
1127 TableList = *Table;
1128 for (Index = 0; Index < TableCount; Index++) {
1129 if ((TableList[Index] != NULL) &&
1130 (TableList[Index]->Signature ==
1132 {
1133 FreePool (TableList[Index]);
1134 } else {
1135 DEBUG ((
1136 DEBUG_ERROR,
1137 "ERROR: SSDT-PCI: Could not free SSDT table at index %d.",
1138 Index
1139 ));
1140 return EFI_INVALID_PARAMETER;
1141 }
1142 } // for
1143
1144 // Free the table list.
1145 FreePool (*Table);
1146
1147 return EFI_SUCCESS;
1148}
1149
1152#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0)
1153
1156STATIC
1158 // ACPI table generator header
1159 {
1160 // Generator ID
1162 // Generator Description
1163 L"ACPI.STD.SSDT.PCI.GENERATOR",
1164 // ACPI Table Signature
1166 // ACPI Table Revision - Unused
1167 0,
1168 // Minimum ACPI Table Revision - Unused
1169 0,
1170 // Creator ID
1172 // Creator Revision
1174 // Build table function. Use the extended version instead.
1175 NULL,
1176 // Free table function. Use the extended version instead.
1177 NULL,
1178 // Extended Build table function.
1180 // Extended free function.
1182 },
1183
1184 // Private fields are defined from here.
1185
1186 // DeviceTable
1187 {
1188 // Table
1189 NULL,
1190 // LastIndex
1191 0,
1192 // MaxIndex
1193 0
1194 },
1195};
1196
1208EFIAPI
1210 IN EFI_HANDLE ImageHandle,
1211 IN EFI_SYSTEM_TABLE *SystemTable
1212 )
1213{
1214 EFI_STATUS Status;
1215
1217 DEBUG ((
1218 DEBUG_INFO,
1219 "SSDT-PCI: Register Generator. Status = %r\n",
1220 Status
1221 ));
1222 ASSERT_EFI_ERROR (Status);
1223 return Status;
1224}
1225
1236EFIAPI
1238 IN EFI_HANDLE ImageHandle,
1239 IN EFI_SYSTEM_TABLE *SystemTable
1240 )
1241{
1242 EFI_STATUS Status;
1243
1245 DEBUG ((
1246 DEBUG_INFO,
1247 "SSDT-PCI: Deregister Generator. Status = %r\n",
1248 Status
1249 ));
1250 ASSERT_EFI_ERROR (Status);
1251 return Status;
1252}
UINT64 UINTN
#define EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
Definition: Acpi63.h:2831
EFI_STATUS EFIAPI AmlGetEisaIdFromString(IN CONST CHAR8 *EisaIdStr, OUT UINT32 *EisaIdInt)
Definition: AcpiHelper.c:155
UINT8 EFIAPI AsciiFromHex(IN UINT8 Hex)
Definition: AcpiHelper.c:25
EFI_STATUS EFIAPI RegisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
EFI_STATUS EFIAPI DeregisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId)
#define TABLE_GENERATOR_CREATOR_ID
@ EStdAcpiTableIdSsdtPciExpress
SSDT Pci Express Generator.
void * AML_ROOT_NODE_HANDLE
Definition: AmlLib.h:51
EFI_STATUS EFIAPI AmlAddPrtEntry(IN UINT32 Address, IN UINT8 Pin, IN CONST CHAR8 *LinkName, IN UINT32 SourceIndex, IN AML_OBJECT_NODE_HANDLE PrtNameNode)
Definition: AmlCodeGen.c:1008
EFI_STATUS EFIAPI AmlCodeGenDevice(IN CONST CHAR8 *NameString, IN AML_NODE_HANDLE ParentNode OPTIONAL, OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL)
EFI_STATUS EFIAPI AmlCodeGenNameResourceTemplate(IN CONST CHAR8 *NameString, IN AML_NODE_HANDLE ParentNode, OPTIONAL OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL)
EFI_STATUS EFIAPI AmlCodeGenRdQWordIo(IN BOOLEAN IsResourceConsumer, IN BOOLEAN IsMinFixed, IN BOOLEAN IsMaxFixed, IN BOOLEAN IsPosDecode, IN UINT8 IsaRanges, IN UINT64 AddressGranularity, IN UINT64 AddressMinimum, IN UINT64 AddressMaximum, IN UINT64 AddressTranslation, IN UINT64 RangeLength, IN UINT8 ResourceSourceIndex, IN CONST CHAR8 *ResourceSource, IN BOOLEAN IsDenseTranslation, IN BOOLEAN IsTypeStatic, IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL)
EFI_STATUS EFIAPI AmlCodeGenScope(IN CONST CHAR8 *NameString, IN AML_NODE_HANDLE ParentNode OPTIONAL, OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL)
EFI_STATUS EFIAPI AmlCodeGenRdDWordMemory(IN BOOLEAN IsResourceConsumer, IN BOOLEAN IsPosDecode, IN BOOLEAN IsMinFixed, IN BOOLEAN IsMaxFixed, IN AML_MEMORY_ATTRIBUTES_MEM Cacheable, IN BOOLEAN IsReadWrite, IN UINT32 AddressGranularity, IN UINT32 AddressMinimum, IN UINT32 AddressMaximum, IN UINT32 AddressTranslation, IN UINT32 RangeLength, IN UINT8 ResourceSourceIndex, IN CONST CHAR8 *ResourceSource, IN AML_MEMORY_ATTRIBUTES_MTP MemoryRangeType, IN BOOLEAN IsTypeStatic, IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL)
EFI_STATUS EFIAPI AmlCodeGenNamePackage(IN CONST CHAR8 *NameString, IN AML_NODE_HANDLE ParentNode, OPTIONAL OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL)
EFI_STATUS EFIAPI AmlCodeGenNameInteger(IN CONST CHAR8 *NameString, IN UINT64 Integer, IN AML_NODE_HANDLE ParentNode OPTIONAL, OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL)
EFI_STATUS EFIAPI AmlAttachNode(IN AML_NODE_HANDLE ParentNode, IN AML_NODE_HANDLE NewNode)
Definition: AmlApi.c:425
void * AML_OBJECT_NODE_HANDLE
Definition: AmlLib.h:55
EFI_STATUS EFIAPI AmlCodeGenRdQWordMemory(IN BOOLEAN IsResourceConsumer, IN BOOLEAN IsPosDecode, IN BOOLEAN IsMinFixed, IN BOOLEAN IsMaxFixed, IN AML_MEMORY_ATTRIBUTES_MEM Cacheable, IN BOOLEAN IsReadWrite, IN UINT64 AddressGranularity, IN UINT64 AddressMinimum, IN UINT64 AddressMaximum, IN UINT64 AddressTranslation, IN UINT64 RangeLength, IN UINT8 ResourceSourceIndex, IN CONST CHAR8 *ResourceSource, IN AML_MEMORY_ATTRIBUTES_MTP MemoryRangeType, IN BOOLEAN IsTypeStatic, IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL)
EFI_STATUS EFIAPI AmlCodeGenRdWordBusNumber(IN BOOLEAN IsResourceConsumer, IN BOOLEAN IsMinFixed, IN BOOLEAN IsMaxFixed, IN BOOLEAN IsPosDecode, IN UINT16 AddressGranularity, IN UINT16 AddressMinimum, IN UINT16 AddressMaximum, IN UINT16 AddressTranslation, IN UINT16 RangeLength, IN UINT8 ResourceSourceIndex, IN CONST CHAR8 *ResourceSource, IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL)
@ EArchCommonObjPciAddressMapInfo
9 - Pci Address Map Info
@ EArchCommonObjCmRef
7 - CM Object Reference
@ EArchCommonObjPciInterruptMapInfo
10 - Pci Interrupt Map Info
@ EArchCommonObjPciConfigSpaceInfo
8 - PCI Configuration Space Info
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)
@ EObjNameSpaceArchCommon
Arch Common Objects Namespace.
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGetBool(TokenName)
Definition: PcdLib.h:401
#define SB_SCOPE
EFI_STATUS EFIAPI AcpiSsdtPcieLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
#define SSDT_PCI_GENERATOR_REVISION
STATIC ACPI_PCI_GENERATOR SsdtPcieGenerator
STATIC EFI_STATUS EFIAPI GenerateMotherboardDevice(IN AML_OBJECT_NODE_HANDLE PciNode, OUT AML_OBJECT_NODE_HANDLE *CrsNode)
STATIC EFI_STATUS EFIAPI BuildSsdtPciTable(IN ACPI_PCI_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN UINT32 Uid, OUT EFI_ACPI_DESCRIPTION_HEADER **Table)
STATIC EFI_STATUS EFIAPI MappingTableInitialize(IN MAPPING_TABLE *MappingTable, IN UINT32 Count)
EFI_STATUS EFIAPI AcpiSsdtPcieLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
STATIC VOID EFIAPI MappingTableFree(IN OUT MAPPING_TABLE *MappingTable)
STATIC UINT32 EFIAPI MappingTableAdd(IN MAPPING_TABLE *MappingTable, IN UINT32 Integer)
STATIC EFI_STATUS EFIAPI GeneratePciCrs(IN ACPI_PCI_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN OUT AML_OBJECT_NODE_HANDLE PciNode)
STATIC EFI_STATUS EFIAPI FreeSsdtPciTableEx(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, IN CONST UINTN TableCount)
STATIC EFI_STATUS EFIAPI BuildSsdtPciTableEx(IN CONST ACPI_TABLE_GENERATOR *This, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, OUT UINTN *CONST TableCount)
STATIC EFI_STATUS EFIAPI GeneratePciDevice(IN ACPI_PCI_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN UINT32 Uid, IN OUT AML_ROOT_NODE_HANDLE *RootNode)
STATIC EFI_STATUS EFIAPI GeneratePciDeviceInfo(IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN UINT32 Uid, IN OUT AML_OBJECT_NODE_HANDLE PciNode)
STATIC EFI_STATUS EFIAPI GeneratePrt(IN ACPI_PCI_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN UINT32 Uid, IN OUT AML_OBJECT_NODE_HANDLE PciNode)
STATIC EFI_STATUS EFIAPI ReserveEcamSpace(IN ACPI_PCI_GENERATOR *Generator, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN OUT AML_OBJECT_NODE_HANDLE PciNode)
#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED
EFI_STATUS EFIAPI GeneratePciSlots(IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN CONST MAPPING_TABLE *MappingTable, IN UINT32 Uid, IN OUT AML_OBJECT_NODE_HANDLE PciNode)
EFI_STATUS EFIAPI AddOscMethod(IN CONST CM_ARCH_COMMON_PCI_CONFIG_SPACE_INFO *PciInfo, IN OUT AML_OBJECT_NODE_HANDLE PciNode)
#define CM_NULL_TOKEN
EFI_STATUS EFIAPI AddSsdtAcpiHeader(IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST ACPI_TABLE_GENERATOR *CONST Generator, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, OUT AML_ROOT_NODE_HANDLE *RootNode)
Definition: TableHelper.c:221
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI AmlDeleteTree(IN AML_NODE_HANDLE Node)
EFI_STATUS EFIAPI AmlSerializeDefinitionBlock(IN AML_ROOT_NODE_HANDLE RootNode, OUT EFI_ACPI_DESCRIPTION_HEADER **Table)
ACPI_TABLE_GENERATOR Header
ACPI Table generator header.
UINT16 PciSegmentGroupNumber
The PCI segment group number.
CM_ARCH_COMMON_GENERIC_INTERRUPT IntcInterrupt
UINT32 MaxIndex
Number of entries in the Table.