mirror of https://github.com/acidanthera/audk.git
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:
parent
29ce755cba
commit
d01defe06b
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue