DynamicTablesPkg: Add support for simple method invocation.

Add support to add Return objects via AML that pass a single integer
argument to the named method.

Signed-off-by: Jeff Brasen <jbrasen@nvidia.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Jeff Brasen 2023-09-18 15:46:58 +00:00 committed by mergify[bot]
parent 8f5505a4c9
commit b2df3ee17f
2 changed files with 292 additions and 0 deletions

View File

@ -1194,6 +1194,60 @@ AmlCodeGenMethodRetInteger (
OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL
); );
/** AML code generation for a method returning a NameString that takes an
integer argument.
AmlCodeGenMethodRetNameStringIntegerArgument (
"MET0", "MET1", 1, TRUE, 3, 5, ParentNode, NewObjectNode
);
is equivalent of the following ASL code:
Method(MET0, 1, Serialized, 3) {
Return (MET1 (5))
}
The ASL parameters "ReturnType" and "ParameterTypes" are not asked
in this function. They are optional parameters in ASL.
@param [in] MethodNameString The new Method's name.
Must be a NULL-terminated ASL NameString
e.g.: "MET0", "_SB.MET0", etc.
The input string is copied.
@param [in] ReturnedNameString The name of the object returned by the
method. Optional parameter, can be:
- NULL (ignored).
- A NULL-terminated ASL NameString.
e.g.: "MET0", "_SB.MET0", etc.
The input string is copied.
@param [in] NumArgs Number of arguments.
Must be 0 <= NumArgs <= 6.
@param [in] IsSerialized TRUE is equivalent to Serialized.
FALSE is equivalent to NotSerialized.
Default is NotSerialized in ASL spec.
@param [in] SyncLevel Synchronization level for the method.
Must be 0 <= SyncLevel <= 15.
Default is 0 in ASL.
@param [in] IntegerArgument Argument to pass to the NameString.
@param [in] ParentNode If provided, set ParentNode as the parent
of the node created.
@param [out] NewObjectNode If success, contains the created node.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AmlCodeGenMethodRetNameStringIntegerArgument (
IN CONST CHAR8 *MethodNameString,
IN CONST CHAR8 *ReturnedNameString OPTIONAL,
IN UINT8 NumArgs,
IN BOOLEAN IsSerialized,
IN UINT8 SyncLevel,
IN UINT64 IntegerArgument,
IN AML_NODE_HANDLE ParentNode OPTIONAL,
OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL
);
/** Create a _LPI name. /** Create a _LPI name.
AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is

View File

@ -1881,6 +1881,132 @@ AmlCodeGenReturnInteger (
return Status; return Status;
} }
/** AML code generation for a Return object node,
returning the object as an input NameString with a integer argument.
AmlCodeGenReturn ("NAM1", 6, ParentNode, NewObjectNode) is
equivalent of the following ASL code:
Return(NAM1 (6))
The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:
DefReturn := ReturnOp ArgObject
ReturnOp := 0xA4
ArgObject := TermArg => DataRefObject
Thus, the ReturnNode must be evaluated as a DataRefObject. It can
be a NameString referencing an object. As this CodeGen Api doesn't
do semantic checking, it is strongly advised to check the AML bytecode
generated by this function against an ASL compiler.
The ReturnNode must be generated inside a Method body scope.
@param [in] NameString The object referenced by this NameString
is returned by the Return ASL statement.
Must be a NULL-terminated ASL NameString
e.g.: "NAM1", "_SB.NAM1", etc.
The input string is copied.
@param [in] Integer Argument to pass to the NameString
@param [in] ParentNode If provided, set ParentNode as the parent
of the node created.
Must be a MethodOp node.
@param [out] NewObjectNode If success, contains the created node.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
STATIC
EFI_STATUS
EFIAPI
AmlCodeGenReturnNameStringIntegerArgument (
IN CONST CHAR8 *NameString,
IN UINT64 Integer,
IN AML_NODE_HEADER *ParentNode OPTIONAL,
OUT AML_OBJECT_NODE **NewObjectNode OPTIONAL
)
{
EFI_STATUS Status;
AML_DATA_NODE *DataNode;
AML_OBJECT_NODE *IntNode;
CHAR8 *AmlNameString;
UINT32 AmlNameStringSize;
AML_OBJECT_NODE *ObjectNode;
DataNode = NULL;
IntNode = NULL;
ObjectNode = NULL;
Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto exit_handler;
}
Status = AmlCodeGenInteger (Integer, &IntNode);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto exit_handler;
}
Status = AmlCreateDataNode (
EAmlNodeDataTypeNameString,
(UINT8 *)AmlNameString,
AmlNameStringSize,
&DataNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto exit_handler1;
}
// AmlCodeGenReturn() deletes DataNode if error.
Status = AmlCodeGenReturn (
(AML_NODE_HEADER *)DataNode,
ParentNode,
&ObjectNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto exit_handler1;
}
Status = AmlVarListAddTail (
(AML_NODE_HANDLE)ObjectNode,
(AML_NODE_HANDLE)IntNode
);
if (EFI_ERROR (Status)) {
// ObjectNode is already attached to ParentNode in AmlCodeGenReturn(),
// so no need to free it here, it will be deleted when deleting the
// ParentNode tree
ASSERT (0);
goto exit_handler1;
}
if (NewObjectNode != 0) {
*NewObjectNode = ObjectNode;
}
goto exit_handler;
exit_handler1:
if (IntNode != NULL) {
AmlDeleteTree ((AML_NODE_HANDLE)IntNode);
}
exit_handler:
if (AmlNameString != NULL) {
FreePool (AmlNameString);
}
return Status;
}
/** AML code generation for a method returning a NameString. /** AML code generation for a method returning a NameString.
AmlCodeGenMethodRetNameString ( AmlCodeGenMethodRetNameString (
@ -1989,6 +2115,118 @@ error_handler:
return Status; return Status;
} }
/** AML code generation for a method returning a NameString that takes an
integer argument.
AmlCodeGenMethodRetNameStringIntegerArgument (
"MET0", "MET1", 1, TRUE, 3, 5, ParentNode, NewObjectNode
);
is equivalent of the following ASL code:
Method(MET0, 1, Serialized, 3) {
Return (MET1 (5))
}
The ASL parameters "ReturnType" and "ParameterTypes" are not asked
in this function. They are optional parameters in ASL.
@param [in] MethodNameString The new Method's name.
Must be a NULL-terminated ASL NameString
e.g.: "MET0", "_SB.MET0", etc.
The input string is copied.
@param [in] ReturnedNameString The name of the object returned by the
method. Optional parameter, can be:
- NULL (ignored).
- A NULL-terminated ASL NameString.
e.g.: "MET0", "_SB.MET0", etc.
The input string is copied.
@param [in] NumArgs Number of arguments.
Must be 0 <= NumArgs <= 6.
@param [in] IsSerialized TRUE is equivalent to Serialized.
FALSE is equivalent to NotSerialized.
Default is NotSerialized in ASL spec.
@param [in] SyncLevel Synchronization level for the method.
Must be 0 <= SyncLevel <= 15.
Default is 0 in ASL.
@param [in] IntegerArgument Argument to pass to the NameString.
@param [in] ParentNode If provided, set ParentNode as the parent
of the node created.
@param [out] NewObjectNode If success, contains the created node.
@retval EFI_SUCCESS Success.
@retval EFI_INVALID_PARAMETER Invalid parameter.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
**/
EFI_STATUS
EFIAPI
AmlCodeGenMethodRetNameStringIntegerArgument (
IN CONST CHAR8 *MethodNameString,
IN CONST CHAR8 *ReturnedNameString OPTIONAL,
IN UINT8 NumArgs,
IN BOOLEAN IsSerialized,
IN UINT8 SyncLevel,
IN UINT64 IntegerArgument,
IN AML_NODE_HANDLE ParentNode OPTIONAL,
OUT AML_OBJECT_NODE_HANDLE *NewObjectNode OPTIONAL
)
{
EFI_STATUS Status;
AML_OBJECT_NODE_HANDLE MethodNode;
if ((MethodNameString == NULL) ||
((ParentNode == NULL) && (NewObjectNode == NULL)))
{
ASSERT (0);
return EFI_INVALID_PARAMETER;
}
// Create a Method named MethodNameString.
Status = AmlCodeGenMethod (
MethodNameString,
NumArgs,
IsSerialized,
SyncLevel,
NULL,
&MethodNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
return Status;
}
// Return ReturnedNameString if provided.
if (ReturnedNameString != NULL) {
Status = AmlCodeGenReturnNameStringIntegerArgument (
ReturnedNameString,
IntegerArgument,
(AML_NODE_HANDLE)MethodNode,
NULL
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
}
Status = LinkNode (
MethodNode,
ParentNode,
NewObjectNode
);
if (EFI_ERROR (Status)) {
ASSERT (0);
goto error_handler;
}
return Status;
error_handler:
if (MethodNode != NULL) {
AmlDeleteTree ((AML_NODE_HANDLE)MethodNode);
}
return Status;
}
/** AML code generation for a method returning an Integer. /** AML code generation for a method returning an Integer.
AmlCodeGenMethodRetInteger ( AmlCodeGenMethodRetInteger (