DynamicTablesPkg: AML Code generation to add _PRT entries

_PRT entries can describe interrupt mapping for Pci devices. The
object is described in ACPI 6.4 s6.2.13 "_PRT (PCI Routing Table)".

Add AmlCodeGenPrtEntry() helper function to add _PRT entries
to an existing _PRT object.

To: Sami Mujawar <sami.mujawar@arm.com>
To: Alexei Fedorov <Alexei.Fedorov@arm.com>
Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Pierre Gondois 2021-12-09 10:25:01 +01:00 committed by mergify[bot]
parent fd5fc4bbb7
commit b2b8def4e3
2 changed files with 266 additions and 0 deletions

View File

@ -891,6 +891,58 @@ AmlCodeGenNameResourceTemplate (
OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL
);
/** Add a _PRT entry.
AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
equivalent of the following ASL code:
Package (4) {
0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
0, // Pin: PCI pin number of the device (0-INTA, ...).
LNKA // Source: Name of the device that allocates the interrupt
// to which the above pin is connected.
0 // Source Index: Source is assumed to only describe one
// interrupt, so let it to index 0.
}
The package is added at the tail of the list of the input _PRT node
name:
Name (_PRT, Package () {
[Pre-existing _PRT entries],
[Newly created _PRT entry]
})
Cf. ACPI 6.4, s6.2.13 "_PRT (PCI Routing Table)"
@ingroup CodeGenApis
@param [in] Address Address. Cf 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).
@param [in] Pin PCI pin number of the device (0-INTA ... 3-INTD).
Must be between 0-3.
@param [in] LinkName Link Name, i.e. device in the AML NameSpace
describing the interrupt used.
The input string is copied.
@param [in] SourceIndex Source index or GSIV.
@param [in] PrtNameNode Prt Named node to add the object to ....
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AmlAddPrtEntry (
IN UINT32 Address,
IN UINT8 Pin,
IN CONST CHAR8 *LinkName,
IN UINT32 SourceIndex,
IN AML_OBJECT_NODE_HANDLE PrtNameNode
);
/** AML code generation for a Device object node.
AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is

View File

@ -868,6 +868,220 @@ AmlCodeGenNameResourceTemplate (
return Status;
}
/** Add a _PRT entry.
AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
equivalent of the following ASL code:
Package (4) {
0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
0, // Pin: PCI pin number of the device (0-INTA, ...).
LNKA // Source: Name of the device that allocates the interrupt
// to which the above pin is connected.
0 // Source Index: Source is assumed to only describe one
// interrupt, so let it to index 0.
}
The package is added at the tail of the list of the input _PRT node
name:
Name (_PRT, Package () {
[Pre-existing _PRT entries],
[Newly created _PRT entry]
})
Cf. ACPI 6.4 specification:
- s6.2.13 "_PRT (PCI Routing Table)"
- s6.1.1 "_ADR (Address)"
@param [in] Address Address. Cf 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).
@param [in] Pin PCI pin number of the device (0-INTA ... 3-INTD).
Must be between 0-3.
@param [in] LinkName Link Name, i.e. device in the AML NameSpace
describing the interrupt used.
The input string is copied.
@param [in] SourceIndex Source index or GSIV.
@param [in] PrtNameNode Prt Named node to add the object to ....
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AmlAddPrtEntry (
IN UINT32 Address,
IN UINT8 Pin,
IN CONST CHAR8 *LinkName,
IN UINT32 SourceIndex,
IN AML_OBJECT_NODE_HANDLE PrtNameNode
)
{
EFI_STATUS Status;
AML_OBJECT_NODE *PrtEntryList;
AML_OBJECT_NODE *PackageNode;
AML_OBJECT_NODE *NewElementNode;
CHAR8 *AmlNameString;
UINT32 AmlNameStringSize;
AML_DATA_NODE *DataNode;
if ((Pin > 3) ||
(LinkName == NULL) ||
(PrtNameNode == NULL) ||
(AmlGetNodeType ((AML_NODE_HANDLE)PrtNameNode) != EAmlNodeObject) ||
(!AmlNodeHasOpCode (PrtNameNode, AML_NAME_OP, 0)) ||
!AmlNameOpCompareName (PrtNameNode, "_PRT"))
{
ASSERT (0);
return EFI_INVALID_PARAMETER;
}
NewElementNode = NULL;
AmlNameString = NULL;
DataNode = NULL;
// Get the Package object node of the _PRT node,
// which is the 2nd fixed argument (i.e. index 1).
PrtEntryList = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
PrtNameNode,
EAmlParseIndexTerm1
);
if ((PrtEntryList == NULL) ||
(AmlGetNodeType ((AML_NODE_HANDLE)PrtEntryList) != EAmlNodeObject) ||
(!AmlNodeHasOpCode (PrtEntryList, AML_PACKAGE_OP, 0)))
{
ASSERT (0);
return EFI_INVALID_PARAMETER;
}
// The new _PRT entry.
Status = AmlCodeGenPackage (&PackageNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlCodeGenInteger (Address, &NewElementNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
Status = AmlVarListAddTail (
(AML_NODE_HANDLE)PackageNode,
(AML_NODE_HANDLE)NewElementNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
NewElementNode = NULL;
Status = AmlCodeGenInteger (Pin, &NewElementNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
Status = AmlVarListAddTail (
(AML_NODE_HANDLE)PackageNode,
(AML_NODE_HANDLE)NewElementNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
NewElementNode = NULL;
Status = ConvertAslNameToAmlName (LinkName, &AmlNameString);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
Status = AmlCreateDataNode (
EAmlNodeDataTypeNameString,
(UINT8 *)AmlNameString,
AmlNameStringSize,
&DataNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
// AmlNameString will be freed before returning.
Status = AmlVarListAddTail (
(AML_NODE_HANDLE)PackageNode,
(AML_NODE_HANDLE)DataNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
DataNode = NULL;
Status = AmlCodeGenInteger (SourceIndex, &NewElementNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
Status = AmlVarListAddTail (
(AML_NODE_HANDLE)PackageNode,
(AML_NODE_HANDLE)NewElementNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
// Append to the the list of _PRT entries.
Status = AmlVarListAddTail (
(AML_NODE_HANDLE)PrtEntryList,
(AML_NODE_HANDLE)PackageNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
// Free AmlNameString before returning as it is copied
// in the call to AmlCreateDataNode().
goto exit_handler;
error_handler:
AmlDeleteTree ((AML_NODE_HANDLE)PackageNode);
if (NewElementNode != NULL) {
AmlDeleteTree ((AML_NODE_HANDLE)NewElementNode);
}
if (DataNode != NULL) {
AmlDeleteTree ((AML_NODE_HANDLE)DataNode);
}
exit_handler:
if (AmlNameString != NULL) {
FreePool (AmlNameString);
}
return Status;
}
/** AML code generation for a Device object node.
AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is