1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096 |
- /** @file
- SSDT Pcie Table Generator.
- Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- @par Reference(s):
- - PCI Firmware Specification - Revision 3.0
- - ACPI 6.4 specification:
- - s6.2.13 "_PRT (PCI Routing Table)"
- - s6.1.1 "_ADR (Address)"
- - linux kernel code
- - Arm Base Boot Requirements v1.0
- - Arm Base System Architecture v1.0
- **/
- #include <Library/AcpiLib.h>
- #include <Library/BaseLib.h>
- #include <Library/BaseMemoryLib.h>
- #include <Library/DebugLib.h>
- #include <Library/MemoryAllocationLib.h>
- #include <Protocol/AcpiTable.h>
- // Module specific include files.
- #include <AcpiTableGenerator.h>
- #include <ConfigurationManagerObject.h>
- #include <ConfigurationManagerHelper.h>
- #include <Library/AcpiHelperLib.h>
- #include <Library/TableHelperLib.h>
- #include <Library/AmlLib/AmlLib.h>
- #include <Library/SsdtPcieSupportLib.h>
- #include <Protocol/ConfigurationManagerProtocol.h>
- #include "SsdtPcieGenerator.h"
- /** ARM standard SSDT Pcie Table Generator.
- Requirements:
- The following Configuration Manager Object(s) are required by
- this Generator:
- - EArmObjCmRef
- - EArmObjPciConfigSpaceInfo
- - EArmObjPciAddressMapInfo
- - EArmObjPciInterruptMapInfo
- */
- /** This macro expands to a function that retrieves the cross-CM-object-
- reference information from the Configuration Manager.
- */
- GET_OBJECT_LIST (
- EObjNameSpaceArm,
- EArmObjCmRef,
- CM_ARM_OBJ_REF
- );
- /** This macro expands to a function that retrieves the Pci
- Configuration Space Information from the Configuration Manager.
- */
- GET_OBJECT_LIST (
- EObjNameSpaceArm,
- EArmObjPciConfigSpaceInfo,
- CM_ARM_PCI_CONFIG_SPACE_INFO
- );
- /** This macro expands to a function that retrieves the Pci
- Address Mapping Information from the Configuration Manager.
- */
- GET_OBJECT_LIST (
- EObjNameSpaceArm,
- EArmObjPciAddressMapInfo,
- CM_ARM_PCI_ADDRESS_MAP_INFO
- );
- /** This macro expands to a function that retrieves the Pci
- Interrupt Mapping Information from the Configuration Manager.
- */
- GET_OBJECT_LIST (
- EObjNameSpaceArm,
- EArmObjPciInterruptMapInfo,
- CM_ARM_PCI_INTERRUPT_MAP_INFO
- );
- /** Initialize the MappingTable.
- @param [in] MappingTable The mapping table structure.
- @param [in] Count Number of entries to allocate in the
- MappingTable.
- @retval EFI_SUCCESS Success.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- MappingTableInitialize (
- IN MAPPING_TABLE *MappingTable,
- IN UINT32 Count
- )
- {
- UINT32 *Table;
- if ((MappingTable == NULL) ||
- (Count == 0))
- {
- ASSERT (0);
- return EFI_INVALID_PARAMETER;
- }
- Table = AllocateZeroPool (sizeof (*Table) * Count);
- if (Table == NULL) {
- ASSERT (0);
- return EFI_OUT_OF_RESOURCES;
- }
- MappingTable->Table = Table;
- MappingTable->LastIndex = 0;
- MappingTable->MaxIndex = Count;
- return EFI_SUCCESS;
- }
- /** Free the MappingTable.
- @param [in, out] MappingTable The mapping table structure.
- **/
- STATIC
- VOID
- EFIAPI
- MappingTableFree (
- IN OUT MAPPING_TABLE *MappingTable
- )
- {
- ASSERT (MappingTable != NULL);
- ASSERT (MappingTable->Table != NULL);
- if (MappingTable->Table != NULL) {
- FreePool (MappingTable->Table);
- }
- }
- /** Add a new entry to the MappingTable and return its index.
- If an entry with [Integer] is already available in the table,
- return its index without adding a new entry.
- @param [in] MappingTable The mapping table structure.
- @param [in] Integer New Integer entry to add.
- @retval The index of the Integer entry in the MappingTable.
- **/
- STATIC
- UINT32
- EFIAPI
- MappingTableAdd (
- IN MAPPING_TABLE *MappingTable,
- IN UINT32 Integer
- )
- {
- UINT32 *Table;
- UINT32 Index;
- UINT32 LastIndex;
- ASSERT (MappingTable != NULL);
- ASSERT (MappingTable->Table != NULL);
- Table = MappingTable->Table;
- LastIndex = MappingTable->LastIndex;
- // Search if there is already an entry with this Integer.
- for (Index = 0; Index < LastIndex; Index++) {
- if (Table[Index] == Integer) {
- return Index;
- }
- }
- ASSERT (LastIndex < MappingTable->MaxIndex);
- // If no, create a new entry.
- Table[LastIndex] = Integer;
- return MappingTable->LastIndex++;
- }
- /** Generate required Pci device information.
- ASL code:
- Name (_UID, <Uid>) // Uid of the Pci device
- Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge
- Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge
- Name (_SEG, <Pci segment group>) // PCI Segment Group number
- Name (_BBN, <Bus number>) // PCI Base Bus Number
- Name (_CCA, 1) // Initially mark the PCI coherent
- @param [in] PciInfo Pci device information.
- @param [in] Uid Unique Id of the Pci device.
- @param [in, out] PciNode Pci node to amend.
- @retval EFI_SUCCESS Success.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- GeneratePciDeviceInfo (
- IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
- IN UINT32 Uid,
- IN OUT AML_OBJECT_NODE_HANDLE PciNode
- )
- {
- EFI_STATUS Status;
- UINT32 EisaId;
- ASSERT (PciInfo != NULL);
- ASSERT (PciNode != NULL);
- // ASL: Name (_UID, <Uid>)
- Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // ASL: Name (_HID, EISAID ("PNP0A08"))
- Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // ASL: Name (_CID, EISAID ("PNP0A03"))
- Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // ASL: Name (_SEG, <Pci segment group>)
- Status = AmlCodeGenNameInteger (
- "_SEG",
- PciInfo->PciSegmentGroupNumber,
- PciNode,
- NULL
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // ASL: Name (_BBN, <Bus number>)
- Status = AmlCodeGenNameInteger (
- "_BBN",
- PciInfo->StartBusNumber,
- PciNode,
- NULL
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // ASL: Name (_CCA, 1)
- // Must be aligned with the IORT CCA property in
- // "Table 14 Memory access properties"
- Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
- /** Generate a _PRT object (Pci Routing Table) for the Pci device.
- Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"
- The first model (defining a _CRS object) is used. This is necessary because
- PCI legacy interrupts are active low and GICv2 SPI interrupts are active
- high.
- Even though PCI interrupts cannot be re-routed, only the first model allows
- to specify the activation state (low/high).
- @param [in] Generator The SSDT Pci generator.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol interface.
- @param [in] PciInfo Pci device information.
- @param [in, out] PciNode Pci node to amend.
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- GeneratePrt (
- IN ACPI_PCI_GENERATOR *Generator,
- IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
- IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
- IN OUT AML_OBJECT_NODE_HANDLE PciNode
- )
- {
- EFI_STATUS Status;
- INT32 Index;
- AML_OBJECT_NODE_HANDLE PrtNode;
- CM_ARM_OBJ_REF *RefInfo;
- UINT32 RefCount;
- CM_ARM_PCI_INTERRUPT_MAP_INFO *IrqMapInfo;
- ASSERT (Generator != NULL);
- ASSERT (CfgMgrProtocol != NULL);
- ASSERT (PciInfo != NULL);
- ASSERT (PciNode != NULL);
- PrtNode = NULL;
- // Get the array of CM_ARM_OBJ_REF referencing the
- // CM_ARM_PCI_INTERRUPT_MAP_INFO objects.
- Status = GetEArmObjCmRef (
- CfgMgrProtocol,
- PciInfo->InterruptMapToken,
- &RefInfo,
- &RefCount
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // Initialized DeviceTable.
- Status = MappingTableInitialize (&Generator->DeviceTable, RefCount);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- goto exit_handler0;
- }
- // ASL: Name (_PRT, Package () {})
- Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- goto exit_handler;
- }
- for (Index = 0; Index < RefCount; Index++) {
- // Get CM_ARM_PCI_INTERRUPT_MAP_INFO structures one by one.
- Status = GetEArmObjPciInterruptMapInfo (
- CfgMgrProtocol,
- RefInfo[Index].ReferenceToken,
- &IrqMapInfo,
- NULL
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- goto exit_handler;
- }
- // Check that the interrupts flags are SPIs, level high.
- // Cf. Arm BSA v1.0, sE.6 "Legacy interrupts"
- if ((Index > 0) &&
- (IrqMapInfo->IntcInterrupt.Interrupt >= 32) &&
- (IrqMapInfo->IntcInterrupt.Interrupt < 1020) &&
- ((IrqMapInfo->IntcInterrupt.Flags & 0xB) != 0))
- {
- Status = EFI_INVALID_PARAMETER;
- ASSERT_EFI_ERROR (Status);
- goto exit_handler;
- }
- // Add the device to the DeviceTable.
- MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice);
- /* Add a _PRT entry.
- ASL
- Name (_PRT, Package () {
- <OldPrtEntries>,
- <NewPrtEntry>
- })
- Address is set as:
- ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
- High word-Device #, Low word-Function #. (for example, device 3,
- function 2 is 0x00030002). To refer to all the functions on a device #,
- use a function number of FFFF).
- */
- Status = AmlAddPrtEntry (
- (IrqMapInfo->PciDevice << 16) | 0xFFFF,
- IrqMapInfo->PciInterrupt,
- NULL,
- IrqMapInfo->IntcInterrupt.Interrupt,
- PrtNode
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- goto exit_handler;
- }
- } // for
- // Attach the _PRT entry.
- Status = AmlAttachNode (PciNode, PrtNode);
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
- goto exit_handler;
- }
- PrtNode = NULL;
- // Generate the Pci slots once all the device have been added.
- Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, PciNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- goto exit_handler;
- }
- exit_handler:
- MappingTableFree (&Generator->DeviceTable);
- exit_handler0:
- if (PrtNode != NULL) {
- AmlDeleteTree (PrtNode);
- }
- return Status;
- }
- /** Generate a _CRS method for the Pci device.
- @param [in] Generator The SSDT Pci generator.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol interface.
- @param [in] PciInfo Pci device information.
- @param [in, out] PciNode Pci node to amend.
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- GeneratePciCrs (
- IN ACPI_PCI_GENERATOR *Generator,
- IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
- IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
- IN OUT AML_OBJECT_NODE_HANDLE PciNode
- )
- {
- EFI_STATUS Status;
- BOOLEAN Translation;
- UINT32 Index;
- CM_ARM_OBJ_REF *RefInfo;
- UINT32 RefCount;
- CM_ARM_PCI_ADDRESS_MAP_INFO *AddrMapInfo;
- AML_OBJECT_NODE_HANDLE CrsNode;
- BOOLEAN IsPosDecode;
- ASSERT (Generator != NULL);
- ASSERT (CfgMgrProtocol != NULL);
- ASSERT (PciInfo != NULL);
- ASSERT (PciNode != NULL);
- // ASL: Name (_CRS, ResourceTemplate () {})
- Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // ASL:
- // WordBusNumber ( // Bus numbers assigned to this root
- // ResourceProducer, MinFixed, MaxFixed, PosDecode,
- // 0, // AddressGranularity
- // <Start>, // AddressMinimum - Minimum Bus Number
- // <End>, // AddressMaximum - Maximum Bus Number
- // 0, // AddressTranslation - Set to 0
- // <End> - <Start> + 1 // RangeLength - Number of Busses
- // )
- Status = AmlCodeGenRdWordBusNumber (
- FALSE,
- TRUE,
- TRUE,
- TRUE,
- 0,
- PciInfo->StartBusNumber,
- PciInfo->EndBusNumber,
- 0,
- PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1,
- 0,
- NULL,
- CrsNode,
- NULL
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // Get the array of CM_ARM_OBJ_REF referencing the
- // CM_ARM_PCI_ADDRESS_MAP_INFO objects.
- Status = GetEArmObjCmRef (
- CfgMgrProtocol,
- PciInfo->AddressMapToken,
- &RefInfo,
- &RefCount
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- for (Index = 0; Index < RefCount; Index++) {
- // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.
- Status = GetEArmObjPciAddressMapInfo (
- CfgMgrProtocol,
- RefInfo[Index].ReferenceToken,
- &AddrMapInfo,
- NULL
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);
- if (AddrMapInfo->CpuAddress >= AddrMapInfo->PciAddress) {
- IsPosDecode = TRUE;
- } else {
- IsPosDecode = FALSE;
- }
- switch (AddrMapInfo->SpaceCode) {
- case PCI_SS_IO:
- Status = AmlCodeGenRdDWordIo (
- FALSE,
- TRUE,
- TRUE,
- IsPosDecode,
- 3,
- 0,
- AddrMapInfo->PciAddress,
- AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
- Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,
- AddrMapInfo->AddressSize,
- 0,
- NULL,
- TRUE,
- FALSE,
- CrsNode,
- NULL
- );
- break;
- case PCI_SS_M32:
- Status = AmlCodeGenRdDWordMemory (
- FALSE,
- IsPosDecode,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- 0,
- AddrMapInfo->PciAddress,
- AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
- Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,
- AddrMapInfo->AddressSize,
- 0,
- NULL,
- 0,
- TRUE,
- CrsNode,
- NULL
- );
- break;
- case PCI_SS_M64:
- Status = AmlCodeGenRdQWordMemory (
- FALSE,
- IsPosDecode,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- 0,
- AddrMapInfo->PciAddress,
- AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
- Translation ? AddrMapInfo->CpuAddress - AddrMapInfo->PciAddress : 0,
- AddrMapInfo->AddressSize,
- 0,
- NULL,
- 0,
- TRUE,
- CrsNode,
- NULL
- );
- break;
- default:
- Status = EFI_INVALID_PARAMETER;
- } // switch
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- } // for
- return Status;
- }
- /** Generate a Pci device.
- @param [in] Generator The SSDT Pci generator.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol interface.
- @param [in] PciInfo Pci device information.
- @param [in] Uid Unique Id of the Pci device.
- @param [in, out] RootNode RootNode of the AML tree to populate.
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
- **/
- STATIC
- EFI_STATUS
- EFIAPI
- GeneratePciDevice (
- IN ACPI_PCI_GENERATOR *Generator,
- IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
- IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
- IN UINT32 Uid,
- IN OUT AML_ROOT_NODE_HANDLE *RootNode
- )
- {
- EFI_STATUS Status;
- CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
- AML_OBJECT_NODE_HANDLE ScopeNode;
- AML_OBJECT_NODE_HANDLE PciNode;
- ASSERT (Generator != NULL);
- ASSERT (CfgMgrProtocol != NULL);
- ASSERT (PciInfo != NULL);
- ASSERT (RootNode != NULL);
- PciNode = NULL;
- // ASL: Scope (\_SB) {}
- Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // Write the name of the PCI device.
- CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);
- AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF);
- if (Uid > 0xF) {
- AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF);
- }
- // ASL: Device (PCIx) {}
- Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // Populate the PCIx node with some Id values.
- Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // Generate the Pci Routing Table (_PRT).
- if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) {
- Status = GeneratePrt (
- Generator,
- CfgMgrProtocol,
- PciInfo,
- PciNode
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- }
- // Generate the _CRS method.
- Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode);
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- // Add the template _OSC method.
- Status = AddOscMethod (PciInfo, PciNode);
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
- /** Build an Ssdt table describing a Pci device.
- @param [in] Generator The SSDT Pci generator.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol interface.
- @param [in] AcpiTableInfo Pointer to the ACPI table information.
- @param [in] PciInfo Pci device information.
- @param [in] Uid Unique Id of the Pci device.
- @param [out] Table If success, contains the created SSDT table.
- @retval EFI_SUCCESS The function completed successfully.
- @retval EFI_INVALID_PARAMETER Invalid parameter.
- @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
- **/
- 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_ARM_PCI_CONFIG_SPACE_INFO *PciInfo,
- IN UINT32 Uid,
- OUT EFI_ACPI_DESCRIPTION_HEADER **Table
- )
- {
- EFI_STATUS Status;
- EFI_STATUS Status1;
- AML_ROOT_NODE_HANDLE RootNode;
- ASSERT (Generator != NULL);
- ASSERT (CfgMgrProtocol != NULL);
- ASSERT (PciInfo != NULL);
- ASSERT (Table != NULL);
- // Create a new Ssdt table.
- Status = AddSsdtAcpiHeader (
- CfgMgrProtocol,
- &Generator->Header,
- AcpiTableInfo,
- &RootNode
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- Status = GeneratePciDevice (
- Generator,
- CfgMgrProtocol,
- PciInfo,
- Uid,
- RootNode
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- goto exit_handler;
- }
- // Serialize the tree.
- Status = AmlSerializeDefinitionBlock (
- RootNode,
- Table
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."
- " Status = %r\n",
- Status
- ));
- }
- exit_handler:
- // Cleanup
- Status1 = AmlDeleteTree (RootNode);
- if (EFI_ERROR (Status1)) {
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI: Failed to cleanup AML tree."
- " Status = %r\n",
- Status1
- ));
- // If Status was success but we failed to delete the AML Tree
- // return Status1 else return the original error code, i.e. Status.
- if (!EFI_ERROR (Status)) {
- return Status1;
- }
- }
- return Status;
- }
- /** Construct SSDT tables describing Pci root complexes.
- This function invokes the Configuration Manager protocol interface
- to get the required hardware information for generating the ACPI
- table.
- If this function allocates any resources then they must be freed
- in the FreeXXXXTableResourcesEx function.
- @param [in] This Pointer to the ACPI table generator.
- @param [in] AcpiTableInfo Pointer to the ACPI table information.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol interface.
- @param [out] Table Pointer to a list of generated ACPI table(s).
- @param [out] TableCount Number of generated ACPI table(s).
- @retval EFI_SUCCESS Table generated successfully.
- @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
- Manager is less than the Object size for
- the requested object.
- @retval EFI_INVALID_PARAMETER A parameter is invalid.
- @retval EFI_NOT_FOUND Could not find information.
- @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
- @retval EFI_UNSUPPORTED Unsupported configuration.
- **/
- 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
- )
- {
- EFI_STATUS Status;
- CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo;
- UINT32 PciCount;
- UINTN Index;
- EFI_ACPI_DESCRIPTION_HEADER **TableList;
- ACPI_PCI_GENERATOR *Generator;
- ASSERT (This != NULL);
- ASSERT (AcpiTableInfo != NULL);
- ASSERT (CfgMgrProtocol != NULL);
- ASSERT (Table != NULL);
- ASSERT (TableCount != NULL);
- ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
- ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
- *TableCount = 0;
- Generator = (ACPI_PCI_GENERATOR *)This;
- Status = GetEArmObjPciConfigSpaceInfo (
- CfgMgrProtocol,
- CM_NULL_TOKEN,
- &PciInfo,
- &PciCount
- );
- if (EFI_ERROR (Status)) {
- ASSERT (0);
- return Status;
- }
- if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI: Too many Pci root complexes: %d."
- " Maximum Pci root complexes supported = %d.\n",
- PciCount,
- MAX_PCI_ROOT_COMPLEXES_SUPPORTED
- ));
- return EFI_INVALID_PARAMETER;
- }
- // Allocate a table to store pointers to the SSDT tables.
- TableList = (EFI_ACPI_DESCRIPTION_HEADER **)
- AllocateZeroPool (
- (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * PciCount)
- );
- if (TableList == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI: Failed to allocate memory for Table List."
- " Status = %r\n",
- Status
- ));
- return Status;
- }
- // Setup the table list early so that appropriate cleanup
- // can be done in case of failure.
- *Table = TableList;
- for (Index = 0; Index < PciCount; Index++) {
- // Build a SSDT table describing the Pci devices.
- Status = BuildSsdtPciTable (
- Generator,
- CfgMgrProtocol,
- AcpiTableInfo,
- &PciInfo[Index],
- Index,
- &TableList[Index]
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI: Failed to build associated SSDT table."
- " Status = %r\n",
- Status
- ));
- goto error_handler;
- }
- *TableCount += 1;
- } // for
- error_handler:
- // Note: Table list and Table count have been setup. The
- // error handler does nothing here as the framework will invoke
- // FreeSsdtPciTableEx () even on failure.
- return Status;
- }
- /** Free any resources allocated for constructing the tables.
- @param [in] This Pointer to the ACPI table generator.
- @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol Interface.
- @param [in, out] Table Pointer to an array of pointers
- to ACPI Table(s).
- @param [in] TableCount Number of ACPI table(s).
- @retval EFI_SUCCESS The resources were freed successfully.
- @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
- **/
- 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
- )
- {
- EFI_ACPI_DESCRIPTION_HEADER **TableList;
- UINTN Index;
- ASSERT (This != NULL);
- ASSERT (AcpiTableInfo != NULL);
- ASSERT (CfgMgrProtocol != NULL);
- ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
- ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
- if ((Table == NULL) ||
- (*Table == NULL) ||
- (TableCount == 0))
- {
- DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n"));
- return EFI_INVALID_PARAMETER;
- }
- TableList = *Table;
- for (Index = 0; Index < TableCount; Index++) {
- if ((TableList[Index] != NULL) &&
- (TableList[Index]->Signature ==
- EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))
- {
- FreePool (TableList[Index]);
- } else {
- DEBUG ((
- DEBUG_ERROR,
- "ERROR: SSDT-PCI: Could not free SSDT table at index %d.",
- Index
- ));
- return EFI_INVALID_PARAMETER;
- }
- } // for
- // Free the table list.
- FreePool (*Table);
- return EFI_SUCCESS;
- }
- /** This macro defines the SSDT Pci Table Generator revision.
- */
- #define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0)
- /** The interface for the SSDT Pci Table Generator.
- */
- STATIC
- ACPI_PCI_GENERATOR SsdtPcieGenerator = {
- // ACPI table generator header
- {
- // Generator ID
- CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),
- // Generator Description
- L"ACPI.STD.SSDT.PCI.GENERATOR",
- // ACPI Table Signature
- EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
- // ACPI Table Revision - Unused
- 0,
- // Minimum ACPI Table Revision - Unused
- 0,
- // Creator ID
- TABLE_GENERATOR_CREATOR_ID_ARM,
- // Creator Revision
- SSDT_PCI_GENERATOR_REVISION,
- // Build table function. Use the extended version instead.
- NULL,
- // Free table function. Use the extended version instead.
- NULL,
- // Extended Build table function.
- BuildSsdtPciTableEx,
- // Extended free function.
- FreeSsdtPciTableEx
- },
- // Private fields are defined from here.
- // DeviceTable
- {
- // Table
- NULL,
- // LastIndex
- 0,
- // MaxIndex
- 0
- },
- };
- /** Register the Generator with the ACPI Table Factory.
- @param [in] ImageHandle The handle to the image.
- @param [in] SystemTable Pointer to the System Table.
- @retval EFI_SUCCESS The Generator is registered.
- @retval EFI_INVALID_PARAMETER A parameter is invalid.
- @retval EFI_ALREADY_STARTED The Generator for the Table ID
- is already registered.
- **/
- EFI_STATUS
- EFIAPI
- AcpiSsdtPcieLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
- DEBUG ((
- DEBUG_INFO,
- "SSDT-PCI: Register Generator. Status = %r\n",
- Status
- ));
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
- /** Deregister the Generator from the ACPI Table Factory.
- @param [in] ImageHandle The handle to the image.
- @param [in] SystemTable Pointer to the System Table.
- @retval EFI_SUCCESS The Generator is deregistered.
- @retval EFI_INVALID_PARAMETER A parameter is invalid.
- @retval EFI_NOT_FOUND The Generator is not registered.
- **/
- EFI_STATUS
- EFIAPI
- AcpiSsdtPcieLibDestructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
- DEBUG ((
- DEBUG_INFO,
- "SSDT-PCI: Deregister Generator. Status = %r\n",
- Status
- ));
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
|