DynamicTablesPkg: AML Code generation to invoke a method

Adds API to generate AML code to invoke/call another
method. Also provides ability to pass arguments of
type integer, string, ArgObj or LocalObj.

Cc: Pierre Gondois <pierre.gondois@arm.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Signed-off-by: Abdul Lateef Attar <AbdulLateef.Attar@amd.com>
Reviewed-by: Pierre Gondois <pierre.gondois@arm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Abdul Lateef Attar 2023-12-18 19:45:11 +05:30 committed by mergify[bot]
parent 29ce755cba
commit d01defe06b
2 changed files with 353 additions and 0 deletions

View File

@ -101,6 +101,56 @@ typedef enum {
AmlAddressRangeMax = 4
} AML_MEMORY_ATTRIBUTES_MTP;
/** Method parameter types
Possible values are:
0 - AmlMethodParamTypeInteger
1 - AmlMethodParamTypeString
2 - AmlMethodParamTypeArg
3 - AmlMethodParamTypeLocal
@par Reference(s)
- ACPI 6.5, s20.2.5 "Term Objects Encoding"
**/
typedef enum {
AmlMethodParamTypeInteger = 0,
AmlMethodParamTypeString = 1,
AmlMethodParamTypeArg = 2,
AmlMethodParamTypeLocal = 3
} AML_METHOD_PARAM_TYPE;
/** AML Method parameter data
holds the AML method parameter data.
**/
typedef union {
UINT8 Arg;
UINT8 Local;
UINT64 Integer;
VOID *Buffer;
} AML_METHOD_PARAM_DATA;
/** structure to hold AML method parameter types
Type - Type of parameter
Data - holds data of parameter
if Type is AmlMethodParamTypeInteger
then Data is of type Integer to hold integer value.
if Type is AmlMethodParamTypeString
then Data contains null terminated string.
If Type is AmlMethodParamTypeArg
then Data contains the Argument number,
0 to 6 are supported value.
If Type is AmlMethodParamTypeLocal
then Data contains the Local variable number,
0 to 7 are supported value.
DataSize - for future use
**/
typedef struct {
AML_METHOD_PARAM_TYPE Type;
AML_METHOD_PARAM_DATA Data;
UINTN DataSize;
} AML_METHOD_PARAM;
/** Parse the definition block.
The function parses the whole AML blob. It starts with the ACPI DSDT/SSDT
@ -1693,4 +1743,66 @@ AmlAddNameStringToNamedPackage (
IN AML_OBJECT_NODE_HANDLE NamedNode
);
/** AML code generation to invoke/call another method.
This method is a subset implementation of MethodInvocation
defined in the ACPI specification 6.5,
section 20.2.5 "Term Objects Encoding".
Added integer, string, ArgObj and LocalObj support.
Example 1:
AmlCodeGenInvokeMethod ("MET0", 0, NULL, ParentNode);
is equivalent to the following ASL code:
MET0 ();
Example 2:
AML_METHOD_PARAM Param[4];
Param[0].Data.Integer = 0x100;
Param[0].Type = AmlMethodParamTypeInteger;
Param[1].Data.Buffer = "TEST";
Param[1].Type = AmlMethodParamTypeString;
Param[2].Data.Arg = 0;
Param[2].Type = AmlMethodParamTypeArg;
Param[3].Data.Local = 2;
Param[3].Type = AmlMethodParamTypeLocal;
AmlCodeGenInvokeMethod ("MET0", 4, Param, ParentNode);
is equivalent to the following ASL code:
MET0 (0x100, "TEST", Arg0, Local2);
Example 3:
AML_METHOD_PARAM Param[2];
Param[0].Data.Arg = 0;
Param[0].Type = AmlMethodParamTypeArg;
Param[1].Data.Integer = 0x100;
Param[1].Type = AmlMethodParamTypeInteger;
AmlCodeGenMethodRetNameString ("MET2", NULL, 2, TRUE, 0, ParentNode, &MethodNode);
AmlCodeGenInvokeMethod ("MET3", 2, Param, MethodNode);
is equivalent to the following ASL code:
Method (MET2, 2, Serialized)
{
MET3 (Arg0, 0x0100)
}
@param [in] MethodNameString The method name to be called or invoked.
@param [in] NumArgs Number of arguments to be passed,
0 to 7 are permissible values.
@param [in] Parameters Contains the parameter data.
@param [in] ParentNode The parent node to which the method invocation
nodes are attached.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AmlCodeGenInvokeMethod (
IN CONST CHAR8 *MethodNameString,
IN UINT8 NumArgs,
IN AML_METHOD_PARAM *Parameters OPTIONAL,
IN AML_NODE_HANDLE ParentNode
);
#endif // AML_LIB_H_

View File

@ -2,6 +2,7 @@
AML Code Generation.
Copyright (c) 2020 - 2022, Arm Limited. All rights reserved.<BR>
Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -3849,3 +3850,243 @@ exit_handler:
return Status;
}
/** AML code generation to invoke/call another method.
This method is a subset implementation of MethodInvocation
defined in the ACPI specification 6.5,
section 20.2.5 "Term Objects Encoding".
Added integer, string, ArgObj and LocalObj support.
Example 1:
AmlCodeGenInvokeMethod ("MET0", 0, NULL, ParentNode);
is equivalent to the following ASL code:
MET0 ();
Example 2:
AML_METHOD_PARAM Param[4];
Param[0].Data.Integer = 0x100;
Param[0].Type = AmlMethodParamTypeInteger;
Param[1].Data.Buffer = "TEST";
Param[1].Type = AmlMethodParamTypeString;
Param[2].Data.Arg = 0;
Param[2].Type = AmlMethodParamTypeArg;
Param[3].Data.Local = 2;
Param[3].Type = AmlMethodParamTypeLocal;
AmlCodeGenInvokeMethod ("MET0", 4, Param, ParentNode);
is equivalent to the following ASL code:
MET0 (0x100, "TEST", Arg0, Local2);
Example 3:
AML_METHOD_PARAM Param[2];
Param[0].Data.Arg = 0;
Param[0].Type = AmlMethodParamTypeArg;
Param[1].Data.Integer = 0x100;
Param[1].Type = AmlMethodParamTypeInteger;
AmlCodeGenMethodRetNameString ("MET2", NULL, 2, TRUE, 0,
ParentNode, &MethodNode);
AmlCodeGenInvokeMethod ("MET3", 2, Param, MethodNode);
is equivalent to the following ASL code:
Method (MET2, 2, Serialized)
{
MET3 (Arg0, 0x0100)
}
@param [in] MethodNameString The method name to be called or invoked.
@param [in] NumArgs Number of arguments to be passed,
0 to 7 are permissible values.
@param [in] Parameters Contains the parameter data.
@param [in] ParentNode The parent node to which the method invocation
nodes are attached.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AmlCodeGenInvokeMethod (
IN CONST CHAR8 *MethodNameString,
IN UINT8 NumArgs,
IN AML_METHOD_PARAM *Parameters OPTIONAL,
IN AML_NODE_HANDLE ParentNode
)
{
EFI_STATUS Status;
UINT8 Index;
CHAR8 *AmlNameString;
UINT32 AmlNameStringSize;
AML_DATA_NODE *DataNode;
AML_OBJECT_NODE *ObjectNode;
AML_NODE_HANDLE *NodeStream;
if ((MethodNameString == NULL) || (ParentNode == NULL)) {
ASSERT (0);
return EFI_INVALID_PARAMETER;
}
if ((NumArgs > 7) ||
((Parameters == NULL) && (NumArgs > 0)))
{
ASSERT (0);
return EFI_INVALID_PARAMETER;
}
/// Allocate space to store methodname, object, data node pointers
NodeStream = AllocateZeroPool (sizeof (AML_NODE_HANDLE) * (NumArgs + 1));
if (NodeStream == NULL) {
ASSERT (0);
return EFI_OUT_OF_RESOURCES;
}
/// Create a called or invoked method name string.
Status = ConvertAslNameToAmlName (MethodNameString, &AmlNameString);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
goto exit_handler;
}
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
FreePool (AmlNameString);
goto exit_handler;
}
DataNode = NULL;
Status = AmlCreateDataNode (
EAmlNodeDataTypeNameString,
(UINT8 *)AmlNameString,
AmlNameStringSize,
&DataNode
);
FreePool (AmlNameString);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
goto exit_handler;
}
NodeStream[0] = (AML_NODE_HANDLE)DataNode;
if (Parameters != NULL) {
/// Validate and convert the Parameters to the stream of nodes.
for (Index = 0; Index < NumArgs; Index++) {
ObjectNode = NULL;
switch (Parameters[Index].Type) {
case AmlMethodParamTypeInteger:
Status = AmlCodeGenInteger (
Parameters[Index].Data.Integer,
&ObjectNode
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
goto exit_handler;
}
break;
case AmlMethodParamTypeString:
if (Parameters[Index].Data.Buffer == NULL) {
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
Status = EFI_INVALID_PARAMETER;
goto exit_handler;
}
Status = AmlCodeGenString (
Parameters[Index].Data.Buffer,
&ObjectNode
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
goto exit_handler;
}
break;
case AmlMethodParamTypeArg:
if (Parameters[Index].Data.Arg > (UINT8)(AML_ARG6 - AML_ARG0)) {
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
Status = EFI_INVALID_PARAMETER;
goto exit_handler;
}
Status = AmlCreateObjectNode (
AmlGetByteEncodingByOpCode (
AML_ARG0 + Parameters[Index].Data.Arg,
0
),
0,
&ObjectNode
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
goto exit_handler;
}
break;
case AmlMethodParamTypeLocal:
if (Parameters[Index].Data.Local > (UINT8)(AML_LOCAL7 - AML_LOCAL0)) {
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
Status = EFI_INVALID_PARAMETER;
goto exit_handler;
}
Status = AmlCreateObjectNode (
AmlGetByteEncodingByOpCode (
AML_LOCAL0 + Parameters[Index].Data.Local,
0
),
0,
&ObjectNode
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
goto exit_handler;
}
break;
default:
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
Status = EFI_INVALID_PARAMETER;
goto exit_handler;
} // switch
// Link the Object Node in the Node Stream.
NodeStream[Index + 1] = (AML_NODE_HANDLE)ObjectNode;
} // for
}
/// Index <= NumArgs, because an additional method name was added.
for (Index = 0; Index <= NumArgs; Index++) {
Status = AmlVarListAddTail (
(AML_NODE_HANDLE)ParentNode,
(AML_NODE_HANDLE)NodeStream[Index]
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
goto exit_handler_detach;
}
}
FreePool (NodeStream);
return Status;
exit_handler_detach:
/// The index contains the last successful node attached.
for ( ; Index > 0; Index--) {
/// Index contains the node number that is failed for AmlVarListAddTail().
/// Hence, start detaching from the last successful
AmlDetachNode (NodeStream[Index-1]);
}
exit_handler:
/// Index <= NumArgs, because an additional method name was added.
for (Index = 0; Index <= NumArgs; Index++) {
if (NodeStream[Index] != 0) {
AmlDeleteTree (NodeStream[Index]);
}
}
FreePool (NodeStream);
return Status;
}