2020-08-05 15:18:20 +02:00
|
|
|
/** @file
|
|
|
|
AML Code Generation.
|
|
|
|
|
2021-10-08 16:46:23 +02:00
|
|
|
Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
|
2020-08-05 15:18:20 +02:00
|
|
|
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <AmlNodeDefines.h>
|
|
|
|
|
|
|
|
#include <AcpiTableGenerator.h>
|
|
|
|
|
|
|
|
#include <AmlCoreInterface.h>
|
|
|
|
#include <AmlEncoding/Aml.h>
|
2021-10-08 16:46:25 +02:00
|
|
|
#include <CodeGen/AmlResourceDataCodeGen.h>
|
2020-08-05 15:18:20 +02:00
|
|
|
#include <Tree/AmlNode.h>
|
|
|
|
#include <Tree/AmlTree.h>
|
|
|
|
#include <String/AmlString.h>
|
|
|
|
#include <Utils/AmlUtility.h>
|
|
|
|
|
|
|
|
/** Utility function to link a node when returning from a CodeGen function.
|
|
|
|
|
|
|
|
@param [in] Node Newly created node.
|
|
|
|
@param [in] ParentNode If provided, set ParentNode as the parent
|
|
|
|
of the node created.
|
2021-10-08 16:46:18 +02:00
|
|
|
@param [out] NewObjectNode If not NULL:
|
|
|
|
- and Success, contains the created Node.
|
|
|
|
- and Error, reset to NULL.
|
2020-08-05 15:18:20 +02:00
|
|
|
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
LinkNode (
|
|
|
|
IN AML_OBJECT_NODE * Node,
|
|
|
|
IN AML_NODE_HEADER * ParentNode,
|
2020-09-21 19:08:56 +02:00
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode
|
2020-08-05 15:18:20 +02:00
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
|
|
|
|
if (NewObjectNode != NULL) {
|
2021-10-08 16:46:18 +02:00
|
|
|
*NewObjectNode = NULL;
|
2020-08-05 15:18:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add RdNode as the last element.
|
|
|
|
if (ParentNode != NULL) {
|
|
|
|
Status = AmlVarListAddTail (ParentNode, (AML_NODE_HEADER*)Node);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-08 16:46:18 +02:00
|
|
|
if (NewObjectNode != NULL) {
|
|
|
|
*NewObjectNode = Node;
|
|
|
|
}
|
|
|
|
|
2020-08-05 15:18:20 +02:00
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for DefinitionBlock.
|
|
|
|
|
|
|
|
Create a Root Node handle.
|
|
|
|
It is the caller's responsibility to free the allocated memory
|
|
|
|
with the AmlDeleteTree function.
|
|
|
|
|
|
|
|
AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
|
|
|
|
equivalent to the following ASL code:
|
|
|
|
DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
|
|
|
|
OemID, TableID, OEMRevision) {}
|
|
|
|
with the ComplianceRevision set to 2 and the AMLFileName is ignored.
|
|
|
|
|
|
|
|
@param[in] TableSignature 4-character ACPI signature.
|
|
|
|
Must be 'DSDT' or 'SSDT'.
|
|
|
|
@param[in] OemId 6-character string OEM identifier.
|
|
|
|
@param[in] OemTableId 8-character string OEM table identifier.
|
|
|
|
@param[in] OemRevision OEM revision number.
|
2020-09-21 19:08:56 +02:00
|
|
|
@param[out] NewRootNode Pointer to the root node representing a
|
2020-08-05 15:18:20 +02:00
|
|
|
Definition Block.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
|
|
**/
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenDefinitionBlock (
|
|
|
|
IN CONST CHAR8 * TableSignature,
|
|
|
|
IN CONST CHAR8 * OemId,
|
|
|
|
IN CONST CHAR8 * OemTableId,
|
|
|
|
IN UINT32 OemRevision,
|
|
|
|
OUT AML_ROOT_NODE ** NewRootNode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_ACPI_DESCRIPTION_HEADER AcpiHeader;
|
|
|
|
|
|
|
|
if ((TableSignature == NULL) ||
|
|
|
|
(OemId == NULL) ||
|
|
|
|
(OemTableId == NULL) ||
|
|
|
|
(NewRootNode == NULL)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyMem (&AcpiHeader.Signature, TableSignature, 4);
|
|
|
|
AcpiHeader.Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
|
|
|
|
AcpiHeader.Revision = 2;
|
|
|
|
CopyMem (&AcpiHeader.OemId, OemId, 6);
|
|
|
|
CopyMem (&AcpiHeader.OemTableId, OemTableId, 8);
|
|
|
|
AcpiHeader.OemRevision = OemRevision;
|
|
|
|
AcpiHeader.CreatorId = TABLE_GENERATOR_CREATOR_ID_ARM;
|
|
|
|
AcpiHeader.CreatorRevision = CREATE_REVISION (1, 0);
|
|
|
|
|
|
|
|
Status = AmlCreateRootNode (&AcpiHeader, NewRootNode);
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for a String object node.
|
|
|
|
|
|
|
|
@param [in] String Pointer to a NULL terminated string.
|
|
|
|
@param [out] NewObjectNode If success, contains the created
|
|
|
|
String object node.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenString (
|
|
|
|
IN CHAR8 * String,
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * ObjectNode;
|
|
|
|
AML_DATA_NODE * DataNode;
|
|
|
|
|
|
|
|
if ((String == NULL) ||
|
|
|
|
(NewObjectNode == NULL)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataNode = NULL;
|
|
|
|
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_STRING_PREFIX, 0),
|
|
|
|
0,
|
|
|
|
&ObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateDataNode (
|
|
|
|
EAmlNodeDataTypeString,
|
|
|
|
(UINT8*)String,
|
|
|
|
(UINT32)AsciiStrLen (String) + 1,
|
|
|
|
&DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
ObjectNode,
|
|
|
|
EAmlParseIndexTerm0,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
*NewObjectNode = ObjectNode;
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
error_handler:
|
2021-10-08 16:46:19 +02:00
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
|
2020-08-05 15:18:20 +02:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for an Integer object node.
|
|
|
|
|
|
|
|
@param [in] Integer Integer of the Integer object node.
|
|
|
|
@param [out] NewObjectNode If success, contains the created
|
|
|
|
Integer object node.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenInteger (
|
|
|
|
IN UINT64 Integer,
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
INT8 ValueWidthDiff;
|
|
|
|
|
|
|
|
if (NewObjectNode == NULL) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create an object node containing Zero.
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0),
|
|
|
|
0,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the object node with integer value.
|
|
|
|
Status = AmlNodeSetIntegerValue (*NewObjectNode, Integer, &ValueWidthDiff);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2021-10-08 16:46:23 +02:00
|
|
|
/** AML code generation for a Package object node.
|
|
|
|
|
|
|
|
The package generated is empty. New elements can be added via its
|
|
|
|
list of variable arguments.
|
|
|
|
|
|
|
|
@param [out] NewObjectNode If success, contains the created
|
|
|
|
Package object node.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenPackage (
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_DATA_NODE * DataNode;
|
|
|
|
UINT8 NodeCount;
|
|
|
|
|
|
|
|
if (NewObjectNode == NULL) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
NodeCount = 0;
|
|
|
|
|
|
|
|
// Create an object node.
|
|
|
|
// PkgLen is 2:
|
|
|
|
// - one byte to store the PkgLength
|
|
|
|
// - one byte for the NumElements.
|
|
|
|
// Cf ACPI6.3, s20.2.5 "Term Objects Encoding"
|
|
|
|
// DefPackage := PackageOp PkgLength NumElements PackageElementList
|
|
|
|
// NumElements := ByteData
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_PACKAGE_OP, 0),
|
|
|
|
2,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NumElements is a ByteData.
|
|
|
|
Status = AmlCreateDataNode (
|
|
|
|
EAmlNodeDataTypeUInt,
|
|
|
|
&NodeCount,
|
|
|
|
sizeof (NodeCount),
|
|
|
|
&DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
*NewObjectNode,
|
|
|
|
EAmlParseIndexTerm0,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
error_handler:
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);
|
|
|
|
if (DataNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2021-10-08 16:46:25 +02:00
|
|
|
/** AML code generation for a Buffer object node.
|
|
|
|
|
|
|
|
To create a Buffer object node with an empty buffer,
|
|
|
|
call the function with (Buffer=NULL, BufferSize=0).
|
|
|
|
|
|
|
|
@param [in] Buffer Buffer to set for the created Buffer
|
|
|
|
object node. The Buffer's content is copied.
|
|
|
|
NULL if there is no buffer to set for
|
|
|
|
the Buffer node.
|
|
|
|
@param [in] BufferSize Size of the Buffer.
|
|
|
|
0 if there is no buffer to set for
|
|
|
|
the Buffer node.
|
|
|
|
@param [out] NewObjectNode If success, contains the created
|
|
|
|
Buffer object node.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenBuffer (
|
|
|
|
IN CONST UINT8 * Buffer, OPTIONAL
|
|
|
|
IN UINT32 BufferSize, OPTIONAL
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * BufferNode;
|
|
|
|
AML_OBJECT_NODE * BufferSizeNode;
|
|
|
|
UINT32 BufferSizeNodeSize;
|
|
|
|
AML_DATA_NODE * DataNode;
|
|
|
|
UINT32 PkgLen;
|
|
|
|
|
|
|
|
// Buffer and BufferSize must be either both set, or both clear.
|
|
|
|
if ((NewObjectNode == NULL) ||
|
|
|
|
((Buffer == NULL) != (BufferSize == 0))) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
BufferNode = NULL;
|
|
|
|
DataNode = NULL;
|
|
|
|
|
|
|
|
// Cf ACPI 6.3 specification, s20.2.5.4 "Type 2 Opcodes Encoding"
|
|
|
|
// DefBuffer := BufferOp PkgLength BufferSize ByteList
|
|
|
|
// BufferOp := 0x11
|
|
|
|
// BufferSize := TermArg => Integer
|
|
|
|
|
|
|
|
Status = AmlCodeGenInteger (BufferSize, &BufferSizeNode);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the number of bytes required to encode the BufferSizeNode.
|
|
|
|
Status = AmlComputeSize (
|
|
|
|
(AML_NODE_HEADER*)BufferSizeNode,
|
|
|
|
&BufferSizeNodeSize
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the size to write in the PkgLen.
|
|
|
|
Status = AmlComputePkgLength (BufferSizeNodeSize + BufferSize, &PkgLen);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create an object node for the buffer.
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_BUFFER_OP, 0),
|
|
|
|
PkgLen,
|
|
|
|
&BufferNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the BufferSizeNode as a fixed argument of the BufferNode.
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
BufferNode,
|
|
|
|
EAmlParseIndexTerm0,
|
|
|
|
(AML_NODE_HEADER*)BufferSizeNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
// BufferSizeNode is now attached.
|
|
|
|
BufferSizeNode = NULL;
|
|
|
|
|
|
|
|
// If there is a buffer, create a DataNode and attach it to the BufferNode.
|
|
|
|
if (Buffer != NULL) {
|
|
|
|
Status = AmlCreateDataNode (
|
|
|
|
EAmlNodeDataTypeRaw,
|
|
|
|
Buffer,
|
|
|
|
BufferSize,
|
|
|
|
&DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlVarListAddTail (
|
|
|
|
(AML_NODE_HEADER*)BufferNode,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*NewObjectNode = BufferNode;
|
|
|
|
return Status;
|
|
|
|
|
|
|
|
error_handler:
|
|
|
|
if (BufferSizeNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)BufferSizeNode);
|
|
|
|
}
|
|
|
|
if (BufferNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)BufferNode);
|
|
|
|
}
|
|
|
|
if (DataNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for a ResourceTemplate.
|
|
|
|
|
|
|
|
"ResourceTemplate" is a macro defined in ACPI 6.3, s19.3.3
|
|
|
|
"ASL Resource Templates". It allows to store resource data elements.
|
|
|
|
|
|
|
|
In AML, a ResourceTemplate is implemented as a Buffer storing resource
|
|
|
|
data elements. An EndTag resource data descriptor must be at the end
|
|
|
|
of the list of resource data elements.
|
|
|
|
This function generates a Buffer node with an EndTag resource data
|
|
|
|
descriptor. It can be seen as an empty list of resource data elements.
|
|
|
|
|
|
|
|
@param [out] NewObjectNode If success, contains the created
|
|
|
|
ResourceTemplate object node.
|
|
|
|
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenResourceTemplate (
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * BufferNode;
|
|
|
|
|
|
|
|
if (NewObjectNode == NULL) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a BufferNode with an empty buffer.
|
|
|
|
Status = AmlCodeGenBuffer (NULL, 0, &BufferNode);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create an EndTag resource data element and attach it to the Buffer.
|
|
|
|
Status = AmlCodeGenEndTag (0, BufferNode, NULL);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)BufferNode);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
*NewObjectNode = BufferNode;
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2020-08-05 15:18:20 +02:00
|
|
|
/** AML code generation for a Name object node.
|
|
|
|
|
|
|
|
@param [in] NameString The new variable name.
|
|
|
|
Must be a NULL-terminated ASL NameString
|
|
|
|
e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
|
This input string is copied.
|
|
|
|
@param [in] Object Object associated 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.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenName (
|
|
|
|
IN CONST CHAR8 * NameString,
|
|
|
|
IN AML_OBJECT_NODE * Object,
|
|
|
|
IN AML_NODE_HEADER * ParentNode, OPTIONAL
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * ObjectNode;
|
|
|
|
AML_DATA_NODE * DataNode;
|
|
|
|
CHAR8 * AmlNameString;
|
|
|
|
UINT32 AmlNameStringSize;
|
|
|
|
|
|
|
|
if ((NameString == NULL) ||
|
|
|
|
(Object == NULL) ||
|
|
|
|
((ParentNode == NULL) && (NewObjectNode == NULL))) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectNode = NULL;
|
|
|
|
DataNode = NULL;
|
|
|
|
AmlNameString = NULL;
|
|
|
|
|
|
|
|
Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_NAME_OP, 0),
|
|
|
|
0,
|
|
|
|
&ObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateDataNode (
|
|
|
|
EAmlNodeDataTypeNameString,
|
|
|
|
(UINT8*)AmlNameString,
|
|
|
|
AmlNameStringSize,
|
|
|
|
&DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
ObjectNode,
|
|
|
|
EAmlParseIndexTerm0,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
ObjectNode,
|
|
|
|
EAmlParseIndexTerm1,
|
|
|
|
(AML_NODE_HEADER*)Object
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = LinkNode (
|
|
|
|
ObjectNode,
|
|
|
|
ParentNode,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free AmlNameString before returning as it is copied
|
|
|
|
// in the call to AmlCreateDataNode().
|
|
|
|
goto error_handler1;
|
|
|
|
|
|
|
|
error_handler2:
|
|
|
|
if (ObjectNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
error_handler1:
|
|
|
|
if (AmlNameString != NULL) {
|
|
|
|
FreePool (AmlNameString);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for a Name object node, containing a String.
|
|
|
|
|
|
|
|
AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
|
|
|
|
equivalent of the following ASL code:
|
|
|
|
Name(_HID, "HID0000")
|
|
|
|
|
|
|
|
@param [in] NameString The new variable name.
|
|
|
|
Must be a NULL-terminated ASL NameString
|
|
|
|
e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
|
The input string is copied.
|
|
|
|
@param [in] String NULL terminated String to associate 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
|
|
|
|
AmlCodeGenNameString (
|
|
|
|
IN CONST CHAR8 * NameString,
|
|
|
|
IN CHAR8 * String,
|
|
|
|
IN AML_NODE_HEADER * ParentNode, OPTIONAL
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * ObjectNode;
|
|
|
|
|
|
|
|
if ((NameString == NULL) ||
|
|
|
|
(String == NULL) ||
|
|
|
|
((ParentNode == NULL) && (NewObjectNode == NULL))) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCodeGenString (String, &ObjectNode);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCodeGenName (
|
|
|
|
NameString,
|
|
|
|
ObjectNode,
|
|
|
|
ParentNode,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for a Name object node, containing an Integer.
|
|
|
|
|
|
|
|
AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
|
|
|
|
equivalent of the following ASL code:
|
|
|
|
Name(_UID, One)
|
|
|
|
|
|
|
|
@param [in] NameString The new variable name.
|
|
|
|
Must be a NULL-terminated ASL NameString
|
|
|
|
e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
|
The input string is copied.
|
|
|
|
@param [in] Integer Integer to associate 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
|
|
|
|
AmlCodeGenNameInteger (
|
|
|
|
IN CONST CHAR8 * NameString,
|
|
|
|
IN UINT64 Integer,
|
|
|
|
IN AML_NODE_HEADER * ParentNode, OPTIONAL
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * ObjectNode;
|
|
|
|
|
|
|
|
if ((NameString == NULL) ||
|
|
|
|
((ParentNode == NULL) && (NewObjectNode == NULL))) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCodeGenInteger (Integer, &ObjectNode);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCodeGenName (
|
|
|
|
NameString,
|
|
|
|
ObjectNode,
|
|
|
|
ParentNode,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for a Device object node.
|
|
|
|
|
|
|
|
AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
|
|
|
|
equivalent of the following ASL code:
|
|
|
|
Device(COM0) {}
|
|
|
|
|
|
|
|
@param [in] NameString The new Device's name.
|
|
|
|
Must be a NULL-terminated ASL NameString
|
|
|
|
e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
|
The input string is copied.
|
|
|
|
@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
|
|
|
|
AmlCodeGenDevice (
|
|
|
|
IN CONST CHAR8 * NameString,
|
|
|
|
IN AML_NODE_HEADER * ParentNode, OPTIONAL
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * ObjectNode;
|
|
|
|
AML_DATA_NODE * DataNode;
|
|
|
|
CHAR8 * AmlNameString;
|
|
|
|
UINT32 AmlNameStringSize;
|
|
|
|
|
|
|
|
if ((NameString == NULL) ||
|
|
|
|
((ParentNode == NULL) && (NewObjectNode == NULL))) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectNode = NULL;
|
|
|
|
DataNode = NULL;
|
|
|
|
AmlNameString = NULL;
|
|
|
|
|
|
|
|
Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_EXT_OP, AML_EXT_DEVICE_OP),
|
|
|
|
AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),
|
|
|
|
&ObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateDataNode (
|
|
|
|
EAmlNodeDataTypeNameString,
|
|
|
|
(UINT8*)AmlNameString,
|
|
|
|
AmlNameStringSize,
|
|
|
|
&DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
ObjectNode,
|
|
|
|
EAmlParseIndexTerm0,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = LinkNode (
|
|
|
|
ObjectNode,
|
|
|
|
ParentNode,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free AmlNameString before returning as it is copied
|
|
|
|
// in the call to AmlCreateDataNode().
|
|
|
|
goto error_handler1;
|
|
|
|
|
|
|
|
error_handler2:
|
|
|
|
if (ObjectNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
error_handler1:
|
|
|
|
if (AmlNameString != NULL) {
|
|
|
|
FreePool (AmlNameString);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** AML code generation for a Scope object node.
|
|
|
|
|
|
|
|
AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
|
|
|
|
equivalent of the following ASL code:
|
|
|
|
Scope(_SB) {}
|
|
|
|
|
|
|
|
@param [in] NameString The new Scope's name.
|
|
|
|
Must be a NULL-terminated ASL NameString
|
|
|
|
e.g.: "DEV0", "DV15.DEV0", etc.
|
|
|
|
The input string is copied.
|
|
|
|
@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
|
|
|
|
AmlCodeGenScope (
|
|
|
|
IN CONST CHAR8 * NameString,
|
|
|
|
IN AML_NODE_HEADER * ParentNode, OPTIONAL
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
AML_OBJECT_NODE * ObjectNode;
|
|
|
|
AML_DATA_NODE * DataNode;
|
|
|
|
CHAR8 * AmlNameString;
|
|
|
|
UINT32 AmlNameStringSize;
|
|
|
|
|
|
|
|
if ((NameString == NULL) ||
|
|
|
|
((ParentNode == NULL) && (NewObjectNode == NULL))) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectNode = NULL;
|
|
|
|
DataNode = NULL;
|
|
|
|
AmlNameString = NULL;
|
|
|
|
|
|
|
|
Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_SCOPE_OP, 0),
|
|
|
|
AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),
|
|
|
|
&ObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateDataNode (
|
|
|
|
EAmlNodeDataTypeNameString,
|
|
|
|
(UINT8*)AmlNameString,
|
|
|
|
AmlNameStringSize,
|
|
|
|
&DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
ObjectNode,
|
|
|
|
EAmlParseIndexTerm0,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = LinkNode (
|
|
|
|
ObjectNode,
|
|
|
|
ParentNode,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free AmlNameString before returning as it is copied
|
|
|
|
// in the call to AmlCreateDataNode().
|
|
|
|
goto error_handler1;
|
|
|
|
|
|
|
|
error_handler2:
|
|
|
|
if (ObjectNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
error_handler1:
|
|
|
|
if (AmlNameString != NULL) {
|
|
|
|
FreePool (AmlNameString);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|
2021-10-08 16:46:26 +02:00
|
|
|
|
|
|
|
/** AML code generation for a Method object node.
|
|
|
|
|
|
|
|
AmlCodeGenMethod ("MET0", 1, TRUE, 3, ParentNode, NewObjectNode) is
|
|
|
|
equivalent of the following ASL code:
|
|
|
|
Method(MET0, 1, Serialized, 3) {}
|
|
|
|
|
|
|
|
ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
|
|
|
|
DefMethod := MethodOp PkgLength NameString MethodFlags TermList
|
|
|
|
MethodOp := 0x14
|
|
|
|
|
|
|
|
The ASL parameters "ReturnType" and "ParameterTypes" are not asked
|
|
|
|
in this function. They are optional parameters in ASL.
|
|
|
|
|
|
|
|
@param [in] NameString 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] 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] 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.
|
|
|
|
**/
|
|
|
|
STATIC
|
|
|
|
EFI_STATUS
|
|
|
|
EFIAPI
|
|
|
|
AmlCodeGenMethod (
|
|
|
|
IN CONST CHAR8 * NameString,
|
|
|
|
IN UINT8 NumArgs,
|
|
|
|
IN BOOLEAN IsSerialized,
|
|
|
|
IN UINT8 SyncLevel,
|
|
|
|
IN AML_NODE_HEADER * ParentNode, OPTIONAL
|
|
|
|
OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
UINT32 PkgLen;
|
|
|
|
UINT8 Flags;
|
|
|
|
AML_OBJECT_NODE * ObjectNode;
|
|
|
|
AML_DATA_NODE * DataNode;
|
|
|
|
CHAR8 * AmlNameString;
|
|
|
|
UINT32 AmlNameStringSize;
|
|
|
|
|
|
|
|
if ((NameString == NULL) ||
|
|
|
|
(NumArgs > 6) ||
|
|
|
|
(SyncLevel > 15) ||
|
|
|
|
((ParentNode == NULL) && (NewObjectNode == NULL))) {
|
|
|
|
ASSERT (0);
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
ObjectNode = NULL;
|
|
|
|
DataNode = NULL;
|
|
|
|
|
|
|
|
// ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
|
|
|
|
// DefMethod := MethodOp PkgLength NameString MethodFlags TermList
|
|
|
|
// MethodOp := 0x14
|
|
|
|
// So:
|
|
|
|
// 1- Create the NameString
|
|
|
|
// 2- Compute the size to write in the PkgLen
|
|
|
|
// 3- Create nodes for the NameString and Method object node
|
|
|
|
// 4- Set the NameString DataNode as a fixed argument
|
|
|
|
// 5- Create and link the MethodFlags node
|
|
|
|
|
|
|
|
// 1- Create the NameString
|
|
|
|
Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2- Compute the size to write in the PkgLen
|
|
|
|
// Add 1 byte (ByteData) for MethodFlags.
|
|
|
|
Status = AmlComputePkgLength (AmlNameStringSize + 1, &PkgLen);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 3- Create nodes for the NameString and Method object node
|
|
|
|
Status = AmlCreateObjectNode (
|
|
|
|
AmlGetByteEncodingByOpCode (AML_METHOD_OP, 0),
|
|
|
|
PkgLen,
|
|
|
|
&ObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler1;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlCreateDataNode (
|
|
|
|
EAmlNodeDataTypeNameString,
|
|
|
|
(UINT8*)AmlNameString,
|
|
|
|
AmlNameStringSize,
|
|
|
|
&DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4- Set the NameString DataNode as a fixed argument
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
ObjectNode,
|
|
|
|
EAmlParseIndexTerm0,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
DataNode = NULL;
|
|
|
|
|
|
|
|
// 5- Create and link the MethodFlags node
|
|
|
|
Flags = NumArgs |
|
|
|
|
(IsSerialized ? BIT3 : 0) |
|
|
|
|
(SyncLevel << 4);
|
|
|
|
|
|
|
|
Status = AmlCreateDataNode (EAmlNodeDataTypeUInt, &Flags, 1, &DataNode);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = AmlSetFixedArgument (
|
|
|
|
ObjectNode,
|
|
|
|
EAmlParseIndexTerm1,
|
|
|
|
(AML_NODE_HEADER*)DataNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Data node is attached so set the pointer to
|
|
|
|
// NULL to ensure correct error handling.
|
|
|
|
DataNode = NULL;
|
|
|
|
|
|
|
|
Status = LinkNode (
|
|
|
|
ObjectNode,
|
|
|
|
ParentNode,
|
|
|
|
NewObjectNode
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
ASSERT (0);
|
|
|
|
goto error_handler2;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Free AmlNameString before returning as it is copied
|
|
|
|
// in the call to AmlCreateDataNode().
|
|
|
|
goto error_handler1;
|
|
|
|
|
|
|
|
error_handler2:
|
|
|
|
if (ObjectNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
|
|
|
|
}
|
|
|
|
if (DataNode != NULL) {
|
|
|
|
AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
error_handler1:
|
|
|
|
if (AmlNameString != NULL) {
|
|
|
|
FreePool (AmlNameString);
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|