From 19a87683654a4969a9f86a3d02199c253c789970 Mon Sep 17 00:00:00 2001 From: Jeff Brasen Date: Fri, 8 Jul 2022 14:59:03 -0600 Subject: DynamicTablesPkg: AcpiSsdtPcieLibArm: Create support library Add support library to allow for customization of _OSC and slot info. The functions in the library are unchanged, with the exception of adding PciInfo pointer to the APIs. Signed-off-by: Jeff Brasen Reviewed-by: Pierre Gondois Reviewed-by: Sami Mujawar --- DynamicTablesPkg/DynamicTables.dsc.inc | 1 + DynamicTablesPkg/DynamicTablesPkg.dec | 3 + DynamicTablesPkg/DynamicTablesPkg.dsc | 1 + .../Include/Library/SsdtPcieSupportLib.h | 73 ++++++++ .../Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 168 +---------------- .../Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h | 21 --- .../Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf | 2 +- .../Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl | 80 --------- .../SsdtPcieSupportLib/SsdtPcieOscTemplate.asl | 80 +++++++++ .../Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c | 200 +++++++++++++++++++++ .../SsdtPcieSupportLib/SsdtPcieSupportLib.inf | 30 ++++ .../SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h | 25 +++ 12 files changed, 417 insertions(+), 267 deletions(-) create mode 100644 DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h delete mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl create mode 100644 DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl create mode 100644 DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c create mode 100644 DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf create mode 100644 DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h (limited to 'DynamicTablesPkg') diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc index 60bcf4b199..3d4fa0c4c4 100644 --- a/DynamicTablesPkg/DynamicTables.dsc.inc +++ b/DynamicTablesPkg/DynamicTables.dsc.inc @@ -15,6 +15,7 @@ [LibraryClasses.common] AcpiHelperLib|DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf + SsdtPcieSupportLib|DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec index 9b74c5a671..cc34c2bdd6 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dec +++ b/DynamicTablesPkg/DynamicTablesPkg.dec @@ -30,6 +30,9 @@ ## @libraryclass Defines a set of APIs to a hardware information parser. HwInfoParserLib|Include/Library/HwInfoParserLib.h + ## @libraryclass Defines functions for customizing the generation of _OSC and slot info. + SsdtPcieSupportLib|Include/Library/SsdtPcieSupportLib.h + ## @libraryclass Defines a set of methods for fixing up a SSDT Serial Port. SsdtSerialPortFixupLib|Include/Library/SsdtSerialPortFixupLib.h diff --git a/DynamicTablesPkg/DynamicTablesPkg.dsc b/DynamicTablesPkg/DynamicTablesPkg.dsc index 068f0bc630..07cc837552 100644 --- a/DynamicTablesPkg/DynamicTablesPkg.dsc +++ b/DynamicTablesPkg/DynamicTablesPkg.dsc @@ -41,6 +41,7 @@ [Components.common] DynamicTablesPkg/Library/Common/AcpiHelperLib/AcpiHelperLib.inf DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf + DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf diff --git a/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h b/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h new file mode 100644 index 0000000000..85e283a994 --- /dev/null +++ b/DynamicTablesPkg/Include/Library/SsdtPcieSupportLib.h @@ -0,0 +1,73 @@ +/** @file + Ssdt PCIe Support Library + + Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef SSDT_PCIE_SUPPORT_LIB_H_ +#define SSDT_PCIE_SUPPORT_LIB_H_ + +#pragma pack(1) + +/** Structure used to map integer to an index. +*/ +typedef struct MappingTable { + /// Mapping table. + /// Contains the Index <-> integer mapping + UINT32 *Table; + + /// Last used index of the Table. + /// Bound by MaxIndex. + UINT32 LastIndex; + + /// Number of entries in the Table. + UINT32 MaxIndex; +} MAPPING_TABLE; + +#pragma pack() + +/** Add an _OSC template method to the PciNode. + + The _OSC method is provided as an AML blob. The blob is + parsed and attached at the end of the PciNode list of variable elements. + + @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. +**/ +EFI_STATUS +EFIAPI +AddOscMethod ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ); + +/** Generate Pci slots devices. + + PCI Firmware Specification - Revision 3.3, + s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot + used. It should be possible to enumerate them, but this is additional + information. + + @param [in] PciInfo Pci device information. + @param [in] MappingTable The mapping table structure. + @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. +**/ +EFI_STATUS +EFIAPI +GeneratePciSlots ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN CONST MAPPING_TABLE *MappingTable, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ); + +#endif // SSDT_PCIE_SUPPORT_LIB_H_ diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c index 3b3d904dbe..ceffe2838c 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "SsdtPcieGenerator.h" @@ -280,86 +281,6 @@ GeneratePciDeviceInfo ( return Status; } -/** Generate Pci slots devices. - - PCI Firmware Specification - Revision 3.3, - s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot - used. It should be possible to enumerate them, but this is additional - information. - - @param [in] MappingTable The mapping table structure. - @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 -GeneratePciSlots ( - IN CONST MAPPING_TABLE *MappingTable, - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - UINT32 Index; - UINT32 LastIndex; - UINT32 DeviceId; - CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; - AML_OBJECT_NODE_HANDLE DeviceNode; - - ASSERT (MappingTable != NULL); - ASSERT (PciNode != NULL); - - // Generic device name is "Dxx". - CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1); - - LastIndex = MappingTable->LastIndex; - - // There are at most 32 devices on a Pci bus. - if (LastIndex >= 32) { - ASSERT (0); - return EFI_INVALID_PARAMETER; - } - - for (Index = 0; Index < LastIndex; Index++) { - DeviceId = MappingTable->Table[Index]; - AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF); - AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF); - - // ASL: - // Device (Dxx) { - // Name (_ADR,
) - // } - Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - /* 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 = AmlCodeGenNameInteger ( - "_ADR", - (DeviceId << 16) | 0xFFFF, - DeviceNode, - NULL - ); - if (EFI_ERROR (Status)) { - ASSERT (0); - return Status; - } - - // _SUN object is not generated as we don't know which slot will be used. - } - - 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)" @@ -495,7 +416,7 @@ GeneratePrt ( PrtNode = NULL; // Generate the Pci slots once all the device have been added. - Status = GeneratePciSlots (&Generator->DeviceTable, PciNode); + Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, PciNode); if (EFI_ERROR (Status)) { ASSERT (0); goto exit_handler; @@ -695,89 +616,6 @@ GeneratePciCrs ( return Status; } -/** Add an _OSC template method to the PciNode. - - The _OSC method is provided as an AML blob. The blob is - parsed and attached at the end of the PciNode list of variable elements. - - @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 -AddOscMethod ( - IN OUT AML_OBJECT_NODE_HANDLE PciNode - ) -{ - EFI_STATUS Status; - EFI_STATUS Status1; - EFI_ACPI_DESCRIPTION_HEADER *SsdtPcieOscTemplate; - AML_ROOT_NODE_HANDLE OscTemplateRoot; - AML_OBJECT_NODE_HANDLE OscNode; - - ASSERT (PciNode != NULL); - - // Parse the Ssdt Pci Osc Template. - SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *) - ssdtpcieosctemplate_aml_code; - - OscNode = NULL; - OscTemplateRoot = NULL; - Status = AmlParseDefinitionBlock ( - SsdtPcieOscTemplate, - &OscTemplateRoot - ); - if (EFI_ERROR (Status)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template." - " Status = %r\n", - Status - )); - return Status; - } - - Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode); - if (EFI_ERROR (Status)) { - goto error_handler; - } - - Status = AmlDetachNode (OscNode); - if (EFI_ERROR (Status)) { - goto error_handler; - } - - Status = AmlAttachNode (PciNode, OscNode); - if (EFI_ERROR (Status)) { - // Free the detached node. - AmlDeleteTree (OscNode); - goto error_handler; - } - -error_handler: - // Cleanup - Status1 = AmlDeleteTree (OscTemplateRoot); - if (EFI_ERROR (Status1)) { - DEBUG (( - DEBUG_ERROR, - "ERROR: SSDT-PCI-OSC: 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; -} - /** Generate a Pci device. @param [in] Generator The SSDT Pci generator. @@ -865,7 +703,7 @@ GeneratePciDevice ( } // Add the template _OSC method. - Status = AddOscMethod (PciNode); + Status = AddOscMethod (PciInfo, PciNode); ASSERT_EFI_ERROR (Status); return Status; } diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h index 515a3e1785..7410f9ffd4 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h @@ -36,29 +36,8 @@ // _SB scope of the AML namespace. #define SB_SCOPE "\\_SB_" -/** C array containing the compiled AML template. - This symbol is defined in the auto generated C file - containing the AML bytecode array. -*/ -extern CHAR8 ssdtpcieosctemplate_aml_code[]; - #pragma pack(1) -/** Structure used to map integer to an index. -*/ -typedef struct MappingTable { - /// Mapping table. - /// Contains the Index <-> integer mapping - UINT32 *Table; - - /// Last used index of the Table. - /// Bound by MaxIndex. - UINT32 LastIndex; - - /// Number of entries in the Table. - UINT32 MaxIndex; -} MAPPING_TABLE; - /** A structure holding the Pcie generator and additional private data. */ typedef struct AcpiPcieGenerator { diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf index 283b564801..b38a4e9d34 100644 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf +++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf @@ -19,7 +19,6 @@ [Sources] SsdtPcieGenerator.c SsdtPcieGenerator.h - SsdtPcieOscTemplate.asl [Packages] DynamicTablesPkg/DynamicTablesPkg.dec @@ -30,3 +29,4 @@ AcpiHelperLib AmlLib BaseLib + SsdtPcieSupportLib diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl deleted file mode 100644 index feaf56b533..0000000000 --- a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl +++ /dev/null @@ -1,80 +0,0 @@ -/** @file - SSDT Pci Osc (Operating System Capabilities) - - Copyright (c) 2021, Arm Limited. All rights reserved.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - - @par Reference(s): - - PCI Firmware Specification - Revision 3.3 - - ACPI 6.4 specification: - - s6.2.13 "_PRT (PCI Routing Table)" - - s6.1.1 "_ADR (Address)" - - linux kernel code -**/ - -DefinitionBlock ("SsdtPciOsc.aml", "SSDT", 2, "ARMLTD", "PCI-OSC", 1) { - - // This table is just a template and is never installed as a table. - // Pci devices are dynamically created at runtime as: - // ASL: - // Device (PCIx) { - // ... - // } - // and the _OSC method available below is appended to the PCIx device as: - // ASL: - // Device (PCIx) { - // ... - // Method (_OSC, 4 { - // ... - // }) - // } - Method (_OSC, 4) { - // - // OS Control Handoff - // - Name (SUPP, Zero) // PCI _OSC Support Field value - Name (CTRL, Zero) // PCI _OSC Control Field value - - // Create DWord-addressable fields from the Capabilities Buffer - CreateDWordField (Arg3, 0, CDW1) - CreateDWordField (Arg3, 4, CDW2) - CreateDWordField (Arg3, 8, CDW3) - - // Check for proper UUID - If (LEqual (Arg0,ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) { - - // Save Capabilities DWord2 & 3 - Store (CDW2, SUPP) - Store (CDW3, CTRL) - - // Only allow native hot plug control if OS supports: - // * ASPM - // * Clock PM - // * MSI/MSI-X - If (LNotEqual (And (SUPP, 0x16), 0x16)) { - And (CTRL, 0x1E, CTRL) // Mask bit 0 (and undefined bits) - } - - // Always allow native PME, AER (no dependencies) - - // Never allow SHPC (no SHPC controller in this system) - And (CTRL, 0x1D, CTRL) - - If (LNotEqual (Arg1, One)) { // Unknown revision - Or (CDW1, 0x08, CDW1) - } - - If (LNotEqual (CDW3, CTRL)) { // Capabilities bits were masked - Or (CDW1, 0x10, CDW1) - } - - // Update DWORD3 in the buffer - Store (CTRL,CDW3) - Return (Arg3) - } Else { - Or (CDW1, 4, CDW1) // Unrecognized UUID - Return (Arg3) - } // If - } // _OSC -} diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl new file mode 100644 index 0000000000..feaf56b533 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieOscTemplate.asl @@ -0,0 +1,80 @@ +/** @file + SSDT Pci Osc (Operating System Capabilities) + + Copyright (c) 2021, Arm Limited. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Reference(s): + - PCI Firmware Specification - Revision 3.3 + - ACPI 6.4 specification: + - s6.2.13 "_PRT (PCI Routing Table)" + - s6.1.1 "_ADR (Address)" + - linux kernel code +**/ + +DefinitionBlock ("SsdtPciOsc.aml", "SSDT", 2, "ARMLTD", "PCI-OSC", 1) { + + // This table is just a template and is never installed as a table. + // Pci devices are dynamically created at runtime as: + // ASL: + // Device (PCIx) { + // ... + // } + // and the _OSC method available below is appended to the PCIx device as: + // ASL: + // Device (PCIx) { + // ... + // Method (_OSC, 4 { + // ... + // }) + // } + Method (_OSC, 4) { + // + // OS Control Handoff + // + Name (SUPP, Zero) // PCI _OSC Support Field value + Name (CTRL, Zero) // PCI _OSC Control Field value + + // Create DWord-addressable fields from the Capabilities Buffer + CreateDWordField (Arg3, 0, CDW1) + CreateDWordField (Arg3, 4, CDW2) + CreateDWordField (Arg3, 8, CDW3) + + // Check for proper UUID + If (LEqual (Arg0,ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) { + + // Save Capabilities DWord2 & 3 + Store (CDW2, SUPP) + Store (CDW3, CTRL) + + // Only allow native hot plug control if OS supports: + // * ASPM + // * Clock PM + // * MSI/MSI-X + If (LNotEqual (And (SUPP, 0x16), 0x16)) { + And (CTRL, 0x1E, CTRL) // Mask bit 0 (and undefined bits) + } + + // Always allow native PME, AER (no dependencies) + + // Never allow SHPC (no SHPC controller in this system) + And (CTRL, 0x1D, CTRL) + + If (LNotEqual (Arg1, One)) { // Unknown revision + Or (CDW1, 0x08, CDW1) + } + + If (LNotEqual (CDW3, CTRL)) { // Capabilities bits were masked + Or (CDW1, 0x10, CDW1) + } + + // Update DWORD3 in the buffer + Store (CTRL,CDW3) + Return (Arg3) + } Else { + Or (CDW1, 4, CDW1) // Unrecognized UUID + Return (Arg3) + } // If + } // _OSC +} diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c new file mode 100644 index 0000000000..e5ab3a3ca8 --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.c @@ -0,0 +1,200 @@ +/** @file + SSDT PCIe Support Library. + + Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.
+ + 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 +#include +#include +#include +#include +#include + +// Module specific include files. +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SsdtPcieSupportLibPrivate.h" + +/** Generate Pci slots devices. + + PCI Firmware Specification - Revision 3.3, + s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot + used. It should be possible to enumerate them, but this is additional + information. + + @param [in] PciInfo Pci device information. + @param [in] MappingTable The mapping table structure. + @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. +**/ +EFI_STATUS +EFIAPI +GeneratePciSlots ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN CONST MAPPING_TABLE *MappingTable, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + UINT32 Index; + UINT32 LastIndex; + UINT32 DeviceId; + CHAR8 AslName[AML_NAME_SEG_SIZE + 1]; + AML_OBJECT_NODE_HANDLE DeviceNode; + + ASSERT (MappingTable != NULL); + ASSERT (PciNode != NULL); + + // Generic device name is "Dxx". + CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1); + + LastIndex = MappingTable->LastIndex; + + // There are at most 32 devices on a Pci bus. + if (LastIndex >= 32) { + ASSERT (0); + return EFI_INVALID_PARAMETER; + } + + for (Index = 0; Index < LastIndex; Index++) { + DeviceId = MappingTable->Table[Index]; + AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF); + AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF); + + // ASL: + // Device (Dxx) { + // Name (_ADR,
) + // } + Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + /* 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 = AmlCodeGenNameInteger ( + "_ADR", + (DeviceId << 16) | 0xFFFF, + DeviceNode, + NULL + ); + if (EFI_ERROR (Status)) { + ASSERT (0); + return Status; + } + + // _SUN object is not generated as we don't know which slot will be used. + } + + return Status; +} + +/** Add an _OSC template method to the PciNode. + + The _OSC method is provided as an AML blob. The blob is + parsed and attached at the end of the PciNode list of variable elements. + + @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. +**/ +EFI_STATUS +EFIAPI +AddOscMethod ( + IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO *PciInfo, + IN OUT AML_OBJECT_NODE_HANDLE PciNode + ) +{ + EFI_STATUS Status; + EFI_STATUS Status1; + EFI_ACPI_DESCRIPTION_HEADER *SsdtPcieOscTemplate; + AML_ROOT_NODE_HANDLE OscTemplateRoot; + AML_OBJECT_NODE_HANDLE OscNode; + + ASSERT (PciNode != NULL); + + // Parse the Ssdt Pci Osc Template. + SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *) + ssdtpcieosctemplate_aml_code; + + OscNode = NULL; + OscTemplateRoot = NULL; + Status = AmlParseDefinitionBlock ( + SsdtPcieOscTemplate, + &OscTemplateRoot + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template." + " Status = %r\n", + Status + )); + return Status; + } + + Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode); + if (EFI_ERROR (Status)) { + goto error_handler; + } + + Status = AmlDetachNode (OscNode); + if (EFI_ERROR (Status)) { + goto error_handler; + } + + Status = AmlAttachNode (PciNode, OscNode); + if (EFI_ERROR (Status)) { + // Free the detached node. + AmlDeleteTree (OscNode); + goto error_handler; + } + +error_handler: + // Cleanup + Status1 = AmlDeleteTree (OscTemplateRoot); + if (EFI_ERROR (Status1)) { + DEBUG (( + DEBUG_ERROR, + "ERROR: SSDT-PCI-OSC: 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; +} diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf new file mode 100644 index 0000000000..57fe32369f --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLib.inf @@ -0,0 +1,30 @@ +## @file +# Ssdt PCIe Support Library. +# +# Copyright (c) 2021, Arm Limited. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION = 0x0001001B + BASE_NAME = SsdtPcieSupportLib + FILE_GUID = 510451a0-60b2-446c-b6bf-59cbe4a41782 + VERSION_STRING = 1.0 + MODULE_TYPE = DXE_DRIVER + LIBRARY_CLASS = SsdtPcieSupportLib + +[Sources] + SsdtPcieSupportLib.c + SsdtPcieSupportLibPrivate.h + SsdtPcieOscTemplate.asl + +[Packages] + DynamicTablesPkg/DynamicTablesPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + AcpiHelperLib + AmlLib + BaseLib diff --git a/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h new file mode 100644 index 0000000000..0c070b8c7b --- /dev/null +++ b/DynamicTablesPkg/Library/Common/SsdtPcieSupportLib/SsdtPcieSupportLibPrivate.h @@ -0,0 +1,25 @@ +/** @file + SSDT PCIe Support Library private data. + + Copyright (c) 2021, Arm Limited. All rights reserved.
+ 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 +**/ + +#ifndef SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_ +#define SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_ + +/** C array containing the compiled AML template. + This symbol is defined in the auto generated C file + containing the AML bytecode array. +*/ +extern CHAR8 ssdtpcieosctemplate_aml_code[]; + +#endif // SSDT_PCIE_SUPPORT_LIB_PRIVATE_H_ -- cgit v1.2.3