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:
committed by
mergify[bot]
parent
29ce755cba
commit
d01defe06b
@ -101,6 +101,56 @@ typedef enum {
|
|||||||
AmlAddressRangeMax = 4
|
AmlAddressRangeMax = 4
|
||||||
} AML_MEMORY_ATTRIBUTES_MTP;
|
} 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.
|
/** Parse the definition block.
|
||||||
|
|
||||||
The function parses the whole AML blob. It starts with the ACPI DSDT/SSDT
|
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
|
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_
|
#endif // AML_LIB_H_
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
AML Code Generation.
|
AML Code Generation.
|
||||||
|
|
||||||
Copyright (c) 2020 - 2022, Arm Limited. All rights reserved.<BR>
|
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
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
**/
|
**/
|
||||||
@ -3849,3 +3850,243 @@ exit_handler:
|
|||||||
|
|
||||||
return Status;
|
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;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user