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 <jbrasen@nvidia.com>
Reviewed-by: Pierre Gondois <pierre.gondois@arm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Jeff Brasen
2022-07-08 14:59:03 -06:00
committed by mergify[bot]
parent 9ac155bf0b
commit 19a8768365
11 changed files with 337 additions and 187 deletions

View File

@@ -0,0 +1,80 @@
/** @file
SSDT Pci Osc (Operating System Capabilities)
Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
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
}

View File

@@ -0,0 +1,200 @@
/** @file
SSDT PCIe Support Library.
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 "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, <address value>)
// }
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;
}

View File

@@ -0,0 +1,30 @@
## @file
# Ssdt PCIe Support Library.
#
# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
#
# 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

View File

@@ -0,0 +1,25 @@
/** @file
SSDT PCIe Support Library private data.
Copyright (c) 2021, 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
**/
#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_