mirror of https://github.com/acidanthera/audk.git
3328 lines
95 KiB
C
3328 lines
95 KiB
C
/** @file
|
|
AML Code Generation.
|
|
|
|
Copyright (c) 2020 - 2022, Arm Limited. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
|
|
|
#include <AmlNodeDefines.h>
|
|
|
|
#include <AcpiTableGenerator.h>
|
|
|
|
#include <AmlCoreInterface.h>
|
|
#include <AmlCpcInfo.h>
|
|
#include <AmlEncoding/Aml.h>
|
|
#include <Api/AmlApiHelper.h>
|
|
#include <CodeGen/AmlResourceDataCodeGen.h>
|
|
#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.
|
|
@param [out] NewObjectNode If not NULL:
|
|
- and Success, contains the created Node.
|
|
- and Error, reset to NULL.
|
|
|
|
@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,
|
|
OUT AML_OBJECT_NODE **NewObjectNode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (NewObjectNode != NULL) {
|
|
*NewObjectNode = NULL;
|
|
}
|
|
|
|
// Add RdNode as the last element.
|
|
if (ParentNode != NULL) {
|
|
Status = AmlVarListAddTail (ParentNode, (AML_NODE_HEADER *)Node);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
if (NewObjectNode != NULL) {
|
|
*NewObjectNode = Node;
|
|
}
|
|
|
|
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.
|
|
@param[out] NewRootNode Pointer to the root node representing a
|
|
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:
|
|
AmlDeleteTree ((AML_NODE_HEADER *)ObjectNode);
|
|
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;
|
|
}
|
|
|
|
/** 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;
|
|
}
|
|
|
|
/** 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;
|
|
}
|
|
|
|
/** 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 Name object node, containing a Package.
|
|
|
|
AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
|
|
equivalent of the following ASL code:
|
|
Name(PKG0, Package () {})
|
|
|
|
@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] 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
|
|
AmlCodeGenNamePackage (
|
|
IN CONST CHAR8 *NameString,
|
|
IN AML_NODE_HEADER *ParentNode, OPTIONAL
|
|
OUT AML_OBJECT_NODE **NewObjectNode OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE *PackageNode;
|
|
|
|
if ((NameString == NULL) ||
|
|
((ParentNode == NULL) && (NewObjectNode == NULL)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = AmlCodeGenPackage (&PackageNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlCodeGenName (
|
|
NameString,
|
|
PackageNode,
|
|
ParentNode,
|
|
NewObjectNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
AmlDeleteTree ((AML_NODE_HEADER *)PackageNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** AML code generation for a Name object node, containing a ResourceTemplate.
|
|
|
|
AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
|
|
equivalent of the following ASL code:
|
|
Name(PRS0, ResourceTemplate () {})
|
|
|
|
@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] 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
|
|
AmlCodeGenNameResourceTemplate (
|
|
IN CONST CHAR8 *NameString,
|
|
IN AML_NODE_HEADER *ParentNode, OPTIONAL
|
|
OUT AML_OBJECT_NODE **NewObjectNode OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE *ResourceTemplateNode;
|
|
|
|
if ((NameString == NULL) ||
|
|
((ParentNode == NULL) && (NewObjectNode == NULL)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlCodeGenName (
|
|
NameString,
|
|
ResourceTemplateNode,
|
|
ParentNode,
|
|
NewObjectNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
AmlDeleteTree ((AML_NODE_HEADER *)ResourceTemplateNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** Add a _PRT entry.
|
|
|
|
AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
|
|
equivalent of the following ASL code:
|
|
Package (4) {
|
|
0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
|
|
0, // Pin: PCI pin number of the device (0-INTA, ...).
|
|
LNKA // Source: Name of the device that allocates the interrupt
|
|
// to which the above pin is connected.
|
|
0 // Source Index: Source is assumed to only describe one
|
|
// interrupt, so let it to index 0.
|
|
}
|
|
|
|
The 2 models described in ACPI 6.4, s6.2.13 "_PRT (PCI Routing Table)" can
|
|
be generated by this function. The example above matches the first model.
|
|
|
|
The package is added at the tail of the list of the input _PRT node
|
|
name:
|
|
Name (_PRT, Package () {
|
|
[Pre-existing _PRT entries],
|
|
[Newly created _PRT entry]
|
|
})
|
|
|
|
Cf. ACPI 6.4 specification:
|
|
- s6.2.13 "_PRT (PCI Routing Table)"
|
|
- s6.1.1 "_ADR (Address)"
|
|
|
|
@param [in] Address Address. Cf ACPI 6.4 specification, Table 6.2:
|
|
"ADR Object Address Encodings":
|
|
High word-Device #, Low word-Function #. (for
|
|
example, device 3, function 2 is 0x00030002).
|
|
To refer to all the functions on a device #,
|
|
use a function number of FFFF).
|
|
@param [in] Pin PCI pin number of the device (0-INTA ... 3-INTD).
|
|
Must be between 0-3.
|
|
@param [in] LinkName Link Name, i.e. device in the AML NameSpace
|
|
describing the interrupt used. The input string
|
|
is copied.
|
|
If NULL, generate 0 in the 'Source' field (cf.
|
|
second model, using GSIV).
|
|
@param [in] SourceIndex Source index or GSIV.
|
|
@param [in] PrtNameNode Prt Named node to add the object to ....
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlAddPrtEntry (
|
|
IN UINT32 Address,
|
|
IN UINT8 Pin,
|
|
IN CONST CHAR8 *LinkName,
|
|
IN UINT32 SourceIndex,
|
|
IN AML_OBJECT_NODE_HANDLE PrtNameNode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE *PrtEntryList;
|
|
AML_OBJECT_NODE *PackageNode;
|
|
AML_OBJECT_NODE *NewElementNode;
|
|
|
|
CHAR8 *AmlNameString;
|
|
UINT32 AmlNameStringSize;
|
|
AML_DATA_NODE *DataNode;
|
|
|
|
if ((Pin > 3) ||
|
|
(PrtNameNode == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)PrtNameNode) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (PrtNameNode, AML_NAME_OP, 0)) ||
|
|
!AmlNameOpCompareName (PrtNameNode, "_PRT"))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
NewElementNode = NULL;
|
|
AmlNameString = NULL;
|
|
DataNode = NULL;
|
|
|
|
// Get the Package object node of the _PRT node,
|
|
// which is the 2nd fixed argument (i.e. index 1).
|
|
PrtEntryList = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
|
|
PrtNameNode,
|
|
EAmlParseIndexTerm1
|
|
);
|
|
if ((PrtEntryList == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)PrtEntryList) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (PrtEntryList, AML_PACKAGE_OP, 0)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// The new _PRT entry.
|
|
Status = AmlCodeGenPackage (&PackageNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlCodeGenInteger (Address, &NewElementNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)NewElementNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
NewElementNode = NULL;
|
|
|
|
Status = AmlCodeGenInteger (Pin, &NewElementNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)NewElementNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
NewElementNode = NULL;
|
|
|
|
if (LinkName != NULL) {
|
|
Status = ConvertAslNameToAmlName (LinkName, &AmlNameString);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlCreateDataNode (
|
|
EAmlNodeDataTypeNameString,
|
|
(UINT8 *)AmlNameString,
|
|
AmlNameStringSize,
|
|
&DataNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
// AmlNameString will be freed be fore returning.
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)DataNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
DataNode = NULL;
|
|
} else {
|
|
Status = AmlCodeGenInteger (0, &NewElementNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)NewElementNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
}
|
|
|
|
Status = AmlCodeGenInteger (SourceIndex, &NewElementNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)NewElementNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
// Append to the list of _PRT entries.
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PrtEntryList,
|
|
(AML_NODE_HANDLE)PackageNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
// Free AmlNameString before returning as it is copied
|
|
// in the call to AmlCreateDataNode().
|
|
goto exit_handler;
|
|
|
|
error_handler:
|
|
AmlDeleteTree ((AML_NODE_HANDLE)PackageNode);
|
|
if (NewElementNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)NewElementNode);
|
|
}
|
|
|
|
if (DataNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)DataNode);
|
|
}
|
|
|
|
exit_handler:
|
|
if (AmlNameString != NULL) {
|
|
FreePool (AmlNameString);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
/** 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;
|
|
}
|
|
|
|
/** AML code generation for a Return object node.
|
|
|
|
AmlCodeGenReturn (ReturnNode, ParentNode, NewObjectNode) is
|
|
equivalent of the following ASL code:
|
|
Return([Content of the ReturnNode])
|
|
|
|
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] ReturnNode The object returned by the Return ASL statement.
|
|
This node is deleted if an error occurs.
|
|
@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
|
|
AmlCodeGenReturn (
|
|
IN AML_NODE_HEADER *ReturnNode,
|
|
IN AML_NODE_HEADER *ParentNode OPTIONAL,
|
|
OUT AML_OBJECT_NODE **NewObjectNode OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE *ObjectNode;
|
|
|
|
if ((ReturnNode == NULL) ||
|
|
((ParentNode == NULL) && (NewObjectNode == NULL)) ||
|
|
((ParentNode != NULL) &&
|
|
!AmlNodeCompareOpCode (
|
|
(AML_OBJECT_NODE *)ParentNode,
|
|
AML_METHOD_OP,
|
|
0
|
|
)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Status = AmlCreateObjectNode (
|
|
AmlGetByteEncodingByOpCode (AML_RETURN_OP, 0),
|
|
0,
|
|
&ObjectNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlSetFixedArgument (
|
|
ObjectNode,
|
|
EAmlParseIndexTerm0,
|
|
ReturnNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
ReturnNode = NULL;
|
|
|
|
Status = LinkNode (
|
|
ObjectNode,
|
|
ParentNode,
|
|
NewObjectNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
return Status;
|
|
|
|
error_handler:
|
|
if (ReturnNode != NULL) {
|
|
AmlDeleteTree (ReturnNode);
|
|
}
|
|
|
|
if (ObjectNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HEADER *)ObjectNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** AML code generation for a Return object node,
|
|
returning the object as an input NameString.
|
|
|
|
AmlCodeGenReturn ("NAM1", ParentNode, NewObjectNode) is
|
|
equivalent of the following ASL code:
|
|
Return(NAM1)
|
|
|
|
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] 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
|
|
AmlCodeGenReturnNameString (
|
|
IN CONST CHAR8 *NameString,
|
|
IN AML_NODE_HEADER *ParentNode OPTIONAL,
|
|
OUT AML_OBJECT_NODE **NewObjectNode OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_DATA_NODE *DataNode;
|
|
CHAR8 *AmlNameString;
|
|
UINT32 AmlNameStringSize;
|
|
|
|
DataNode = 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 = AmlCreateDataNode (
|
|
EAmlNodeDataTypeNameString,
|
|
(UINT8 *)AmlNameString,
|
|
AmlNameStringSize,
|
|
&DataNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto exit_handler;
|
|
}
|
|
|
|
// AmlCodeGenReturn() deletes DataNode if error.
|
|
Status = AmlCodeGenReturn (
|
|
(AML_NODE_HEADER *)DataNode,
|
|
ParentNode,
|
|
NewObjectNode
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
exit_handler:
|
|
if (AmlNameString != NULL) {
|
|
FreePool (AmlNameString);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** AML code generation for a Return object node,
|
|
returning an Integer.
|
|
|
|
AmlCodeGenReturn (0), ParentNode, NewObjectNode) is
|
|
equivalent of the following ASL code:
|
|
Return (0)
|
|
|
|
The ACPI 6.3 specification, 20.2.8 "Statement Opcodes Encoding" states:
|
|
DefReturn := ReturnOp ArgObject
|
|
ReturnOp := 0xA4
|
|
ArgObject := TermArg => DataRefObject
|
|
|
|
Thus, the ReturnNode must be evaluated as a DataRefObject.
|
|
|
|
The ReturnNode must be generated inside a Method body scope.
|
|
|
|
@param [in] Integer The integer is returned by the Return
|
|
ASL statement.
|
|
@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
|
|
AmlCodeGenReturnInteger (
|
|
IN UINT64 Integer,
|
|
IN AML_NODE_HEADER *ParentNode OPTIONAL,
|
|
OUT AML_OBJECT_NODE **NewObjectNode OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE *IntNode;
|
|
|
|
IntNode = NULL;
|
|
|
|
Status = AmlCodeGenInteger (Integer, &IntNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
// AmlCodeGenReturn() deletes DataNode if error.
|
|
Status = AmlCodeGenReturn (
|
|
(AML_NODE_HEADER *)IntNode,
|
|
ParentNode,
|
|
NewObjectNode
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** AML code generation for a method returning a NameString.
|
|
|
|
AmlCodeGenMethodRetNameString (
|
|
"MET0", "_CRS", 1, TRUE, 3, ParentNode, NewObjectNode
|
|
);
|
|
is equivalent of the following ASL code:
|
|
Method(MET0, 1, Serialized, 3) {
|
|
Return (_CRS)
|
|
}
|
|
|
|
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] 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
|
|
AmlCodeGenMethodRetNameString (
|
|
IN CONST CHAR8 *MethodNameString,
|
|
IN CONST CHAR8 *ReturnedNameString OPTIONAL,
|
|
IN UINT8 NumArgs,
|
|
IN BOOLEAN IsSerialized,
|
|
IN UINT8 SyncLevel,
|
|
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 = AmlCodeGenReturnNameString (
|
|
ReturnedNameString,
|
|
(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.
|
|
|
|
AmlCodeGenMethodRetInteger (
|
|
"_CBA", 0, 1, TRUE, 3, ParentNode, NewObjectNode
|
|
);
|
|
is equivalent of the following ASL code:
|
|
Method(_CBA, 1, Serialized, 3) {
|
|
Return (0)
|
|
}
|
|
|
|
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] ReturnedInteger The value of the integer returned by the
|
|
method.
|
|
@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.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlCodeGenMethodRetInteger (
|
|
IN CONST CHAR8 *MethodNameString,
|
|
IN UINT64 ReturnedInteger,
|
|
IN UINT8 NumArgs,
|
|
IN BOOLEAN IsSerialized,
|
|
IN UINT8 SyncLevel,
|
|
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;
|
|
}
|
|
|
|
Status = AmlCodeGenReturnInteger (
|
|
ReturnedInteger,
|
|
(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;
|
|
}
|
|
|
|
/** Create a _LPI name.
|
|
|
|
AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is
|
|
equivalent of the following ASL code:
|
|
Name (_LPI, Package (
|
|
0, // Revision
|
|
1, // LevelId
|
|
0 // Count
|
|
))
|
|
|
|
This function doesn't define any LPI state. As shown above, the count
|
|
of _LPI state is set to 0.
|
|
The AmlAddLpiState () function allows to add LPI states.
|
|
|
|
Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
|
|
|
|
@param [in] LpiNameString The new LPI 's object name.
|
|
Must be a NULL-terminated ASL NameString
|
|
e.g.: "_LPI", "DEV0.PLPI", etc.
|
|
The input string is copied.
|
|
@param [in] Revision Revision number of the _LPI states.
|
|
@param [in] LevelId A platform defined number that identifies the
|
|
level of hierarchy of the processor node to
|
|
which the LPI states apply.
|
|
@param [in] ParentNode If provided, set ParentNode as the parent
|
|
of the node created.
|
|
@param [out] NewLpiNode If success, contains the created node.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlCreateLpiNode (
|
|
IN CONST CHAR8 *LpiNameString,
|
|
IN UINT16 Revision,
|
|
IN UINT64 LevelId,
|
|
IN AML_NODE_HANDLE ParentNode OPTIONAL,
|
|
OUT AML_OBJECT_NODE_HANDLE *NewLpiNode OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE_HANDLE PackageNode;
|
|
AML_OBJECT_NODE_HANDLE IntegerNode;
|
|
|
|
if ((LpiNameString == NULL) ||
|
|
((ParentNode == NULL) && (NewLpiNode == NULL)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
Status = AmlCodeGenPackage (&PackageNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
// Create and attach Revision
|
|
Status = AmlCodeGenInteger (Revision, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// Create and attach LevelId
|
|
Status = AmlCodeGenInteger (LevelId, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// Create and attach Count. No LPI state is added, so 0.
|
|
Status = AmlCodeGenInteger (0, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
Status = AmlCodeGenName (LpiNameString, PackageNode, ParentNode, NewLpiNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
return Status;
|
|
|
|
error_handler:
|
|
AmlDeleteTree ((AML_NODE_HANDLE)PackageNode);
|
|
if (IntegerNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** Add an _LPI state to a LPI node created using AmlCreateLpiNode.
|
|
|
|
AmlAddLpiState increments the Count of LPI states in the LPI node by one,
|
|
and adds the following package:
|
|
Package() {
|
|
MinResidency,
|
|
WorstCaseWakeLatency,
|
|
Flags,
|
|
ArchFlags,
|
|
ResCntFreq,
|
|
EnableParentState,
|
|
(GenericRegisterDescriptor != NULL) ? // Entry method. If a
|
|
ResourceTemplate(GenericRegisterDescriptor) : // Register is given,
|
|
Integer, // use it. Use the
|
|
// Integer otherwise.
|
|
ResourceTemplate() { // NULL Residency Counter
|
|
Register (SystemMemory, 0, 0, 0, 0)
|
|
},
|
|
ResourceTemplate() { // NULL Usage Counter
|
|
Register (SystemMemory, 0, 0, 0, 0)
|
|
},
|
|
"" // NULL State Name
|
|
},
|
|
|
|
Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
|
|
|
|
@param [in] MinResidency Minimum Residency.
|
|
@param [in] WorstCaseWakeLatency Worst case wake-up latency.
|
|
@param [in] Flags Flags.
|
|
@param [in] ArchFlags Architectural flags.
|
|
@param [in] ResCntFreq Residency Counter Frequency.
|
|
@param [in] EnableParentState Enabled Parent State.
|
|
@param [in] GenericRegisterDescriptor Entry Method.
|
|
If not NULL, use this Register to
|
|
describe the entry method address.
|
|
@param [in] Integer Entry Method.
|
|
If GenericRegisterDescriptor is NULL,
|
|
take this value.
|
|
@param [in] ResidencyCounterRegister If not NULL, use it to populate the
|
|
residency counter register.
|
|
@param [in] UsageCounterRegister If not NULL, use it to populate the
|
|
usage counter register.
|
|
@param [in] StateName If not NULL, use it to populate the
|
|
state name.
|
|
@param [in] LpiNode Lpi node created with the function
|
|
AmlCreateLpiNode to which the new LPI
|
|
state is appended.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlAddLpiState (
|
|
IN UINT32 MinResidency,
|
|
IN UINT32 WorstCaseWakeLatency,
|
|
IN UINT32 Flags,
|
|
IN UINT32 ArchFlags,
|
|
IN UINT32 ResCntFreq,
|
|
IN UINT32 EnableParentState,
|
|
IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *GenericRegisterDescriptor OPTIONAL,
|
|
IN UINT64 Integer OPTIONAL,
|
|
IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *ResidencyCounterRegister OPTIONAL,
|
|
IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE *UsageCounterRegister OPTIONAL,
|
|
IN CHAR8 *StateName OPTIONAL,
|
|
IN AML_OBJECT_NODE_HANDLE LpiNode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_DATA_NODE_HANDLE RdNode;
|
|
AML_OBJECT_NODE_HANDLE PackageNode;
|
|
AML_OBJECT_NODE_HANDLE IntegerNode;
|
|
AML_OBJECT_NODE_HANDLE StringNode;
|
|
AML_OBJECT_NODE_HANDLE NewLpiPackageNode;
|
|
AML_OBJECT_NODE_HANDLE ResourceTemplateNode;
|
|
|
|
UINT32 Index;
|
|
AML_OBJECT_NODE_HANDLE CountNode;
|
|
UINT64 Count;
|
|
|
|
if ((LpiNode == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)LpiNode) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (LpiNode, AML_NAME_OP, 0)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
RdNode = 0;
|
|
StringNode = NULL;
|
|
IntegerNode = NULL;
|
|
ResourceTemplateNode = NULL;
|
|
|
|
// AmlCreateLpiNode () created a LPI container such as:
|
|
// Name (_LPI, Package (
|
|
// 0, // Revision
|
|
// 1, // LevelId
|
|
// 0 // Count
|
|
// ))
|
|
// Get the LPI container, a PackageOp object node stored as the 2nd fixed
|
|
// argument (i.e. index 1) of LpiNode.
|
|
PackageNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
|
|
LpiNode,
|
|
EAmlParseIndexTerm1
|
|
);
|
|
if ((PackageNode == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
CountNode = NULL;
|
|
// The third variable argument is the LPI Count node.
|
|
for (Index = 0; Index < 3; Index++) {
|
|
CountNode = (AML_OBJECT_NODE_HANDLE)AmlGetNextVariableArgument (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)CountNode
|
|
);
|
|
if (CountNode == NULL) {
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
Status = AmlNodeGetIntegerValue (CountNode, &Count);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlUpdateInteger (CountNode, Count + 1);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlCodeGenPackage (&NewLpiPackageNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
return Status;
|
|
}
|
|
|
|
// MinResidency
|
|
Status = AmlCodeGenInteger (MinResidency, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// WorstCaseWakeLatency
|
|
Status = AmlCodeGenInteger (WorstCaseWakeLatency, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// Flags
|
|
Status = AmlCodeGenInteger (Flags, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// ArchFlags
|
|
Status = AmlCodeGenInteger (ArchFlags, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// ResCntFreq
|
|
Status = AmlCodeGenInteger (ResCntFreq, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// EnableParentState
|
|
Status = AmlCodeGenInteger (EnableParentState, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
|
|
// Entry Method
|
|
if (GenericRegisterDescriptor != NULL) {
|
|
// Entry Method: As a Register resource data
|
|
Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
ResourceTemplateNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlCodeGenRdRegister (
|
|
GenericRegisterDescriptor->AddressSpaceId,
|
|
GenericRegisterDescriptor->RegisterBitWidth,
|
|
GenericRegisterDescriptor->RegisterBitOffset,
|
|
GenericRegisterDescriptor->Address,
|
|
GenericRegisterDescriptor->AccessSize,
|
|
NULL,
|
|
&RdNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
RdNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
RdNode = NULL;
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)ResourceTemplateNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
ResourceTemplateNode = NULL;
|
|
} else {
|
|
// Entry Method: As an integer
|
|
Status = AmlCodeGenInteger (Integer, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
IntegerNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
IntegerNode = NULL;
|
|
}
|
|
|
|
// Residency Counter Register.
|
|
Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
ResourceTemplateNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
if (ResidencyCounterRegister != NULL) {
|
|
Status = AmlCodeGenRdRegister (
|
|
ResidencyCounterRegister->AddressSpaceId,
|
|
ResidencyCounterRegister->RegisterBitWidth,
|
|
ResidencyCounterRegister->RegisterBitOffset,
|
|
ResidencyCounterRegister->Address,
|
|
ResidencyCounterRegister->AccessSize,
|
|
NULL,
|
|
&RdNode
|
|
);
|
|
} else {
|
|
Status = AmlCodeGenRdRegister (
|
|
EFI_ACPI_6_4_SYSTEM_MEMORY,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
&RdNode
|
|
);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
RdNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
RdNode = NULL;
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)ResourceTemplateNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
ResourceTemplateNode = NULL;
|
|
|
|
// Usage Counter Register.
|
|
Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
ResourceTemplateNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
if (UsageCounterRegister != NULL) {
|
|
Status = AmlCodeGenRdRegister (
|
|
UsageCounterRegister->AddressSpaceId,
|
|
UsageCounterRegister->RegisterBitWidth,
|
|
UsageCounterRegister->RegisterBitOffset,
|
|
UsageCounterRegister->Address,
|
|
UsageCounterRegister->AccessSize,
|
|
NULL,
|
|
&RdNode
|
|
);
|
|
} else {
|
|
Status = AmlCodeGenRdRegister (
|
|
EFI_ACPI_6_4_SYSTEM_MEMORY,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
&RdNode
|
|
);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
RdNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
RdNode = NULL;
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)ResourceTemplateNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
ResourceTemplateNode = NULL;
|
|
|
|
// State name.
|
|
if (UsageCounterRegister != NULL) {
|
|
Status = AmlCodeGenString (StateName, &StringNode);
|
|
} else {
|
|
Status = AmlCodeGenString ("", &StringNode);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
StringNode = NULL;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewLpiPackageNode,
|
|
(AML_NODE_HANDLE)StringNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
StringNode = NULL;
|
|
|
|
// Add the new LPI state to the LpiNode.
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)NewLpiPackageNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT (0);
|
|
goto error_handler;
|
|
}
|
|
|
|
return Status;
|
|
|
|
error_handler:
|
|
if (RdNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)RdNode);
|
|
}
|
|
|
|
if (NewLpiPackageNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)NewLpiPackageNode);
|
|
}
|
|
|
|
if (StringNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)StringNode);
|
|
}
|
|
|
|
if (IntegerNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);
|
|
}
|
|
|
|
if (ResourceTemplateNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** AML code generation for a _DSD device data object.
|
|
|
|
AmlAddDeviceDataDescriptorPackage (Uuid, DsdNode, PackageNode) is
|
|
equivalent of the following ASL code:
|
|
ToUUID(Uuid),
|
|
Package () {}
|
|
|
|
Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)".
|
|
|
|
_DSD (Device Specific Data) Implementation Guide
|
|
https://github.com/UEFI/DSD-Guide
|
|
Per s3. "'Well-Known _DSD UUIDs and Data Structure Formats'"
|
|
If creating a Device Properties data then UUID daffd814-6eba-4d8c-8a91-bc9bbf4aa301 should be used.
|
|
|
|
@param [in] Uuid The Uuid of the descriptor to be created
|
|
@param [in] DsdNode Node of the DSD Package.
|
|
@param [out] PackageNode If success, contains the created package node.
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlAddDeviceDataDescriptorPackage (
|
|
IN CONST EFI_GUID *Uuid,
|
|
IN AML_OBJECT_NODE_HANDLE DsdNode,
|
|
OUT AML_OBJECT_NODE_HANDLE *PackageNode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE *UuidNode;
|
|
AML_DATA_NODE *UuidDataNode;
|
|
AML_OBJECT_NODE_HANDLE DsdEntryList;
|
|
|
|
if ((Uuid == NULL) ||
|
|
(PackageNode == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)DsdNode) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (DsdNode, AML_NAME_OP, 0)) ||
|
|
!AmlNameOpCompareName (DsdNode, "_DSD"))
|
|
{
|
|
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Get the Package object node of the _DSD node,
|
|
// which is the 2nd fixed argument (i.e. index 1).
|
|
DsdEntryList = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
|
|
DsdNode,
|
|
EAmlParseIndexTerm1
|
|
);
|
|
if ((DsdEntryList == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)DsdEntryList) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (DsdEntryList, AML_PACKAGE_OP, 0)))
|
|
{
|
|
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
*PackageNode = NULL;
|
|
UuidDataNode = NULL;
|
|
|
|
Status = AmlCodeGenBuffer (NULL, 0, &UuidNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlCreateDataNode (
|
|
EAmlNodeDataTypeRaw,
|
|
(CONST UINT8 *)Uuid,
|
|
sizeof (EFI_GUID),
|
|
&UuidDataNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HEADER *)UuidNode,
|
|
(AML_NODE_HEADER *)UuidDataNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
UuidDataNode = NULL;
|
|
|
|
// Append to the list of _DSD entries.
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)DsdEntryList,
|
|
(AML_NODE_HANDLE)UuidNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlCodeGenPackage (PackageNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler_detach;
|
|
}
|
|
|
|
// Append to the list of _DSD entries.
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)DsdEntryList,
|
|
(AML_NODE_HANDLE)*PackageNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler_detach;
|
|
}
|
|
|
|
return Status;
|
|
|
|
error_handler_detach:
|
|
if (UuidNode != NULL) {
|
|
AmlDetachNode ((AML_NODE_HANDLE)UuidNode);
|
|
}
|
|
|
|
error_handler:
|
|
if (UuidNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)UuidNode);
|
|
}
|
|
|
|
if (*PackageNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)*PackageNode);
|
|
*PackageNode = NULL;
|
|
}
|
|
|
|
if (UuidDataNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)UuidDataNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** AML code generation to add a package with a name and value,
|
|
to a parent package.
|
|
This is useful to build the _DSD package but can be used in other cases.
|
|
|
|
AmlAddNameIntegerPackage ("Name", Value, PackageNode) is
|
|
equivalent of the following ASL code:
|
|
Package (2) {"Name", Value}
|
|
|
|
Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)".
|
|
|
|
@param [in] Name String to place in first entry of package
|
|
@param [in] Value Integer to place in second entry of package
|
|
@param [in] PackageNode Package to add new sub package to.
|
|
|
|
@retval EFI_SUCCESS Success.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlAddNameIntegerPackage (
|
|
IN CHAR8 *Name,
|
|
IN UINT64 Value,
|
|
IN AML_OBJECT_NODE_HANDLE PackageNode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE *NameNode;
|
|
AML_OBJECT_NODE *ValueNode;
|
|
AML_OBJECT_NODE *NewPackageNode;
|
|
|
|
if ((Name == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0)))
|
|
{
|
|
ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
NameNode = NULL;
|
|
ValueNode = NULL;
|
|
|
|
// The new package entry.
|
|
Status = AmlCodeGenPackage (&NewPackageNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlCodeGenString (Name, &NameNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewPackageNode,
|
|
(AML_NODE_HANDLE)NameNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
NameNode = NULL;
|
|
|
|
Status = AmlCodeGenInteger (Value, &ValueNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)NewPackageNode,
|
|
(AML_NODE_HANDLE)ValueNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
ValueNode = NULL;
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)NewPackageNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
return Status;
|
|
|
|
error_handler:
|
|
if (NewPackageNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)NewPackageNode);
|
|
}
|
|
|
|
if (NameNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)NameNode);
|
|
}
|
|
|
|
if (ValueNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)ValueNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** Adds a register to the package
|
|
|
|
@ingroup CodeGenApis
|
|
|
|
@param [in] Register If provided, register that will be added to package.
|
|
otherwise NULL register will be added
|
|
@param [in] PackageNode Package to add value to
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlAddRegisterToPackage (
|
|
IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE *Register OPTIONAL,
|
|
IN AML_OBJECT_NODE_HANDLE PackageNode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_DATA_NODE_HANDLE RdNode;
|
|
AML_OBJECT_NODE_HANDLE ResourceTemplateNode;
|
|
|
|
RdNode = NULL;
|
|
|
|
Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
if (Register != NULL) {
|
|
Status = AmlCodeGenRdRegister (
|
|
Register->AddressSpaceId,
|
|
Register->RegisterBitWidth,
|
|
Register->RegisterBitOffset,
|
|
Register->Address,
|
|
Register->AccessSize,
|
|
NULL,
|
|
&RdNode
|
|
);
|
|
} else {
|
|
Status = AmlCodeGenRdRegister (
|
|
EFI_ACPI_6_4_SYSTEM_MEMORY,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
NULL,
|
|
&RdNode
|
|
);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAppendRdNode (ResourceTemplateNode, RdNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
RdNode = NULL;
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)ResourceTemplateNode
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
return Status;
|
|
|
|
error_handler:
|
|
if (RdNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)RdNode);
|
|
}
|
|
|
|
if (ResourceTemplateNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)ResourceTemplateNode);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** Utility function to check if generic address points to NULL
|
|
|
|
@param [in] Address Pointer to the Generic address
|
|
|
|
@retval TRUE Address is system memory with an Address of 0.
|
|
@retval FALSE Address does not point to NULL.
|
|
**/
|
|
STATIC
|
|
BOOLEAN
|
|
EFIAPI
|
|
IsNullGenericAddress (
|
|
IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE *Address
|
|
)
|
|
{
|
|
if ((Address == NULL) ||
|
|
((Address->AddressSpaceId == EFI_ACPI_6_4_SYSTEM_MEMORY) &&
|
|
(Address->Address == 0x0)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/** Adds an integer or register to the package
|
|
|
|
@ingroup CodeGenApis
|
|
|
|
@param [in] Register If provided, register that will be added to package
|
|
@param [in] Integer If Register is NULL, integer that will be added to the package
|
|
@param [in] PackageNode Package to add value to
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlAddRegisterOrIntegerToPackage (
|
|
IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE *Register OPTIONAL,
|
|
IN UINT32 Integer,
|
|
IN AML_OBJECT_NODE_HANDLE PackageNode
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE_HANDLE IntegerNode;
|
|
|
|
IntegerNode = NULL;
|
|
|
|
if (!IsNullGenericAddress (Register)) {
|
|
Status = AmlAddRegisterToPackage (Register, PackageNode);
|
|
} else {
|
|
Status = AmlCodeGenInteger (Integer, &IntegerNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
Status = AmlVarListAddTail (
|
|
(AML_NODE_HANDLE)PackageNode,
|
|
(AML_NODE_HANDLE)IntegerNode
|
|
);
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
if (IntegerNode != NULL) {
|
|
AmlDeleteTree ((AML_NODE_HANDLE)IntegerNode);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/** Create a _CPC node.
|
|
|
|
Creates and optionally adds the following node
|
|
Name(_CPC, Package()
|
|
{
|
|
NumEntries, // Integer
|
|
Revision, // Integer
|
|
HighestPerformance, // Integer or Buffer (Resource Descriptor)
|
|
NominalPerformance, // Integer or Buffer (Resource Descriptor)
|
|
LowestNonlinearPerformance, // Integer or Buffer (Resource Descriptor)
|
|
LowestPerformance, // Integer or Buffer (Resource Descriptor)
|
|
GuaranteedPerformanceRegister, // Buffer (Resource Descriptor)
|
|
DesiredPerformanceRegister , // Buffer (Resource Descriptor)
|
|
MinimumPerformanceRegister , // Buffer (Resource Descriptor)
|
|
MaximumPerformanceRegister , // Buffer (Resource Descriptor)
|
|
PerformanceReductionToleranceRegister, // Buffer (Resource Descriptor)
|
|
TimeWindowRegister, // Buffer (Resource Descriptor)
|
|
CounterWraparoundTime, // Integer or Buffer (Resource Descriptor)
|
|
ReferencePerformanceCounterRegister, // Buffer (Resource Descriptor)
|
|
DeliveredPerformanceCounterRegister, // Buffer (Resource Descriptor)
|
|
PerformanceLimitedRegister, // Buffer (Resource Descriptor)
|
|
CPPCEnableRegister // Buffer (Resource Descriptor)
|
|
AutonomousSelectionEnable, // Integer or Buffer (Resource Descriptor)
|
|
AutonomousActivityWindowRegister, // Buffer (Resource Descriptor)
|
|
EnergyPerformancePreferenceRegister, // Buffer (Resource Descriptor)
|
|
ReferencePerformance // Integer or Buffer (Resource Descriptor)
|
|
LowestFrequency, // Integer or Buffer (Resource Descriptor)
|
|
NominalFrequency // Integer or Buffer (Resource Descriptor)
|
|
})
|
|
|
|
If resource buffer is NULL then integer will be used.
|
|
|
|
Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
|
|
|
|
@ingroup CodeGenApis
|
|
|
|
@param [in] CpcInfo CpcInfo object
|
|
@param [in] ParentNode If provided, set ParentNode as the parent
|
|
of the node created.
|
|
@param [out] NewCpcNode If success and provided, contains the created node.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
AmlCreateCpcNode (
|
|
IN AML_CPC_INFO *CpcInfo,
|
|
IN AML_NODE_HANDLE ParentNode OPTIONAL,
|
|
OUT AML_OBJECT_NODE_HANDLE *NewCpcNode OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
AML_OBJECT_NODE_HANDLE CpcNode;
|
|
AML_OBJECT_NODE_HANDLE CpcPackage;
|
|
UINT32 NumberOfEntries;
|
|
|
|
if ((CpcInfo == NULL) ||
|
|
((ParentNode == NULL) && (NewCpcNode == NULL)))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Revision 3 per ACPI 6.4 specification
|
|
if (CpcInfo->Revision == 3) {
|
|
// NumEntries 23 per ACPI 6.4 specification
|
|
NumberOfEntries = 23;
|
|
} else {
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((IsNullGenericAddress (&CpcInfo->HighestPerformanceBuffer) &&
|
|
(CpcInfo->HighestPerformanceInteger == 0)) ||
|
|
(IsNullGenericAddress (&CpcInfo->NominalPerformanceBuffer) &&
|
|
(CpcInfo->NominalPerformanceInteger == 0)) ||
|
|
(IsNullGenericAddress (&CpcInfo->LowestNonlinearPerformanceBuffer) &&
|
|
(CpcInfo->LowestNonlinearPerformanceInteger == 0)) ||
|
|
(IsNullGenericAddress (&CpcInfo->LowestPerformanceBuffer) &&
|
|
(CpcInfo->LowestPerformanceInteger == 0)) ||
|
|
IsNullGenericAddress (&CpcInfo->DesiredPerformanceRegister) ||
|
|
IsNullGenericAddress (&CpcInfo->ReferencePerformanceCounterRegister) ||
|
|
IsNullGenericAddress (&CpcInfo->DeliveredPerformanceCounterRegister) ||
|
|
IsNullGenericAddress (&CpcInfo->PerformanceLimitedRegister))
|
|
{
|
|
ASSERT (0);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
CpcPackage = NULL;
|
|
|
|
Status = AmlCodeGenNamePackage ("_CPC", NULL, &CpcNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
return Status;
|
|
}
|
|
|
|
// Get the Package object node of the _CPC node,
|
|
// which is the 2nd fixed argument (i.e. index 1).
|
|
CpcPackage = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
|
|
CpcNode,
|
|
EAmlParseIndexTerm1
|
|
);
|
|
if ((CpcPackage == NULL) ||
|
|
(AmlGetNodeType ((AML_NODE_HANDLE)CpcPackage) != EAmlNodeObject) ||
|
|
(!AmlNodeHasOpCode (CpcPackage, AML_PACKAGE_OP, 0)))
|
|
{
|
|
ASSERT (0);
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
NULL,
|
|
NumberOfEntries,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
NULL,
|
|
CpcInfo->Revision,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->HighestPerformanceBuffer,
|
|
CpcInfo->HighestPerformanceInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->NominalPerformanceBuffer,
|
|
CpcInfo->NominalPerformanceInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->LowestNonlinearPerformanceBuffer,
|
|
CpcInfo->LowestNonlinearPerformanceInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->LowestPerformanceBuffer,
|
|
CpcInfo->LowestPerformanceInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->GuaranteedPerformanceRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->DesiredPerformanceRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->MinimumPerformanceRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->MaximumPerformanceRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->PerformanceReductionToleranceRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->TimeWindowRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->CounterWraparoundTimeBuffer,
|
|
CpcInfo->CounterWraparoundTimeInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->ReferencePerformanceCounterRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->DeliveredPerformanceCounterRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->PerformanceLimitedRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->CPPCEnableRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->AutonomousSelectionEnableBuffer,
|
|
CpcInfo->AutonomousSelectionEnableInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->AutonomousActivityWindowRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterToPackage (&CpcInfo->EnergyPerformancePreferenceRegister, CpcPackage);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->ReferencePerformanceBuffer,
|
|
CpcInfo->ReferencePerformanceInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->LowestFrequencyBuffer,
|
|
CpcInfo->LowestFrequencyInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = AmlAddRegisterOrIntegerToPackage (
|
|
&CpcInfo->NominalFrequencyBuffer,
|
|
CpcInfo->NominalFrequencyInteger,
|
|
CpcPackage
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
Status = LinkNode (CpcNode, ParentNode, NewCpcNode);
|
|
if (EFI_ERROR (Status)) {
|
|
ASSERT_EFI_ERROR (Status);
|
|
goto error_handler;
|
|
}
|
|
|
|
return Status;
|
|
|
|
error_handler:
|
|
AmlDeleteTree ((AML_NODE_HANDLE)CpcNode);
|
|
return Status;
|
|
}
|