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

@ -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;
}