--- /dev/null
+/** @file\r
+ AML Code Generation.\r
+\r
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <AmlNodeDefines.h>\r
+\r
+#include <AcpiTableGenerator.h>\r
+\r
+#include <AmlCoreInterface.h>\r
+#include <AmlEncoding/Aml.h>\r
+#include <Tree/AmlNode.h>\r
+#include <Tree/AmlTree.h>\r
+#include <String/AmlString.h>\r
+#include <Utils/AmlUtility.h>\r
+\r
+/** Utility function to link a node when returning from a CodeGen function.\r
+\r
+ @param [in] Node Newly created node.\r
+ @param [in] ParentNode If provided, set ParentNode as the parent\r
+ of the node created.\r
+ @param [out] NewObjectNode If success, contains the created object node.\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+LinkNode (\r
+ IN AML_OBJECT_NODE * Node,\r
+ IN AML_NODE_HEADER * ParentNode,\r
+ IN AML_OBJECT_NODE ** NewObjectNode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (NewObjectNode != NULL) {\r
+ *NewObjectNode = Node;\r
+ }\r
+\r
+ // Add RdNode as the last element.\r
+ if (ParentNode != NULL) {\r
+ Status = AmlVarListAddTail (ParentNode, (AML_NODE_HEADER*)Node);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/** AML code generation for DefinitionBlock.\r
+\r
+ Create a Root Node handle.\r
+ It is the caller's responsibility to free the allocated memory\r
+ with the AmlDeleteTree function.\r
+\r
+ AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is\r
+ equivalent to the following ASL code:\r
+ DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,\r
+ OemID, TableID, OEMRevision) {}\r
+ with the ComplianceRevision set to 2 and the AMLFileName is ignored.\r
+\r
+ @param[in] TableSignature 4-character ACPI signature.\r
+ Must be 'DSDT' or 'SSDT'.\r
+ @param[in] OemId 6-character string OEM identifier.\r
+ @param[in] OemTableId 8-character string OEM table identifier.\r
+ @param[in] OemRevision OEM revision number.\r
+ @param[out] DefinitionBlockTerm The ASL Term handle representing a\r
+ Definition Block.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenDefinitionBlock (\r
+ IN CONST CHAR8 * TableSignature,\r
+ IN CONST CHAR8 * OemId,\r
+ IN CONST CHAR8 * OemTableId,\r
+ IN UINT32 OemRevision,\r
+ OUT AML_ROOT_NODE ** NewRootNode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_DESCRIPTION_HEADER AcpiHeader;\r
+\r
+ if ((TableSignature == NULL) ||\r
+ (OemId == NULL) ||\r
+ (OemTableId == NULL) ||\r
+ (NewRootNode == NULL)) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ CopyMem (&AcpiHeader.Signature, TableSignature, 4);\r
+ AcpiHeader.Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);\r
+ AcpiHeader.Revision = 2;\r
+ CopyMem (&AcpiHeader.OemId, OemId, 6);\r
+ CopyMem (&AcpiHeader.OemTableId, OemTableId, 8);\r
+ AcpiHeader.OemRevision = OemRevision;\r
+ AcpiHeader.CreatorId = TABLE_GENERATOR_CREATOR_ID_ARM;\r
+ AcpiHeader.CreatorRevision = CREATE_REVISION (1, 0);\r
+\r
+ Status = AmlCreateRootNode (&AcpiHeader, NewRootNode);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return Status;\r
+}\r
+\r
+/** AML code generation for a String object node.\r
+\r
+ @param [in] String Pointer to a NULL terminated string.\r
+ @param [out] NewObjectNode If success, contains the created\r
+ String object node.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenString (\r
+ IN CHAR8 * String,\r
+ OUT AML_OBJECT_NODE ** NewObjectNode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ AML_OBJECT_NODE * ObjectNode;\r
+ AML_DATA_NODE * DataNode;\r
+\r
+ if ((String == NULL) ||\r
+ (NewObjectNode == NULL)) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ObjectNode = NULL;\r
+ DataNode = NULL;\r
+\r
+ Status = AmlCreateObjectNode (\r
+ AmlGetByteEncodingByOpCode (AML_STRING_PREFIX, 0),\r
+ 0,\r
+ &ObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ Status = AmlCreateDataNode (\r
+ EAmlNodeDataTypeString,\r
+ (UINT8*)String,\r
+ (UINT32)AsciiStrLen (String) + 1,\r
+ &DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler;\r
+ }\r
+\r
+ Status = AmlSetFixedArgument (\r
+ ObjectNode,\r
+ EAmlParseIndexTerm0,\r
+ (AML_NODE_HEADER*)DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
+ goto error_handler;\r
+ }\r
+\r
+ *NewObjectNode = ObjectNode;\r
+ return Status;\r
+\r
+error_handler:\r
+ if (ObjectNode != NULL) {\r
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** AML code generation for an Integer object node.\r
+\r
+ @param [in] Integer Integer of the Integer object node.\r
+ @param [out] NewObjectNode If success, contains the created\r
+ Integer object node.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenInteger (\r
+ IN UINT64 Integer,\r
+ OUT AML_OBJECT_NODE ** NewObjectNode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ INT8 ValueWidthDiff;\r
+\r
+ if (NewObjectNode == NULL) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ // Create an object node containing Zero.\r
+ Status = AmlCreateObjectNode (\r
+ AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0),\r
+ 0,\r
+ NewObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ // Update the object node with integer value.\r
+ Status = AmlNodeSetIntegerValue (*NewObjectNode, Integer, &ValueWidthDiff);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** AML code generation for a Name object node.\r
+\r
+ @param [in] NameString The new variable name.\r
+ Must be a NULL-terminated ASL NameString\r
+ e.g.: "DEV0", "DV15.DEV0", etc.\r
+ This input string is copied.\r
+ @param [in] Object Object associated to the NameString.\r
+ @param [in] ParentNode If provided, set ParentNode as the parent\r
+ of the node created.\r
+ @param [out] NewObjectNode If success, contains the created node.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenName (\r
+ IN CONST CHAR8 * NameString,\r
+ IN AML_OBJECT_NODE * Object,\r
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL\r
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ AML_OBJECT_NODE * ObjectNode;\r
+ AML_DATA_NODE * DataNode;\r
+ CHAR8 * AmlNameString;\r
+ UINT32 AmlNameStringSize;\r
+\r
+ if ((NameString == NULL) ||\r
+ (Object == NULL) ||\r
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ObjectNode = NULL;\r
+ DataNode = NULL;\r
+ AmlNameString = NULL;\r
+\r
+ Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler1;\r
+ }\r
+\r
+ Status = AmlCreateObjectNode (\r
+ AmlGetByteEncodingByOpCode (AML_NAME_OP, 0),\r
+ 0,\r
+ &ObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler1;\r
+ }\r
+\r
+ Status = AmlCreateDataNode (\r
+ EAmlNodeDataTypeNameString,\r
+ (UINT8*)AmlNameString,\r
+ AmlNameStringSize,\r
+ &DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler2;\r
+ }\r
+\r
+ Status = AmlSetFixedArgument (\r
+ ObjectNode,\r
+ EAmlParseIndexTerm0,\r
+ (AML_NODE_HEADER*)DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
+ goto error_handler2;\r
+ }\r
+\r
+ Status = AmlSetFixedArgument (\r
+ ObjectNode,\r
+ EAmlParseIndexTerm1,\r
+ (AML_NODE_HEADER*)Object\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler2;\r
+ }\r
+\r
+ Status = LinkNode (\r
+ ObjectNode,\r
+ ParentNode,\r
+ NewObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler2;\r
+ }\r
+\r
+ // Free AmlNameString before returning as it is copied\r
+ // in the call to AmlCreateDataNode().\r
+ goto error_handler1;\r
+\r
+error_handler2:\r
+ if (ObjectNode != NULL) {\r
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
+ }\r
+\r
+error_handler1:\r
+ if (AmlNameString != NULL) {\r
+ FreePool (AmlNameString);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** AML code generation for a Name object node, containing a String.\r
+\r
+ AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is\r
+ equivalent of the following ASL code:\r
+ Name(_HID, "HID0000")\r
+\r
+ @param [in] NameString The new variable name.\r
+ Must be a NULL-terminated ASL NameString\r
+ e.g.: "DEV0", "DV15.DEV0", etc.\r
+ The input string is copied.\r
+ @param [in] String NULL terminated String to associate to the\r
+ NameString.\r
+ @param [in] ParentNode If provided, set ParentNode as the parent\r
+ of the node created.\r
+ @param [out] NewObjectNode If success, contains the created node.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenNameString (\r
+ IN CONST CHAR8 * NameString,\r
+ IN CHAR8 * String,\r
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL\r
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ AML_OBJECT_NODE * ObjectNode;\r
+\r
+ if ((NameString == NULL) ||\r
+ (String == NULL) ||\r
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = AmlCodeGenString (String, &ObjectNode);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ Status = AmlCodeGenName (\r
+ NameString,\r
+ ObjectNode,\r
+ ParentNode,\r
+ NewObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** AML code generation for a Name object node, containing an Integer.\r
+\r
+ AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is\r
+ equivalent of the following ASL code:\r
+ Name(_UID, One)\r
+\r
+ @param [in] NameString The new variable name.\r
+ Must be a NULL-terminated ASL NameString\r
+ e.g.: "DEV0", "DV15.DEV0", etc.\r
+ The input string is copied.\r
+ @param [in] Integer Integer to associate to the NameString.\r
+ @param [in] ParentNode If provided, set ParentNode as the parent\r
+ of the node created.\r
+ @param [out] NewObjectNode If success, contains the created node.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenNameInteger (\r
+ IN CONST CHAR8 * NameString,\r
+ IN UINT64 Integer,\r
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL\r
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ AML_OBJECT_NODE * ObjectNode;\r
+\r
+ if ((NameString == NULL) ||\r
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = AmlCodeGenInteger (Integer, &ObjectNode);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ Status = AmlCodeGenName (\r
+ NameString,\r
+ ObjectNode,\r
+ ParentNode,\r
+ NewObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** AML code generation for a Device object node.\r
+\r
+ AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is\r
+ equivalent of the following ASL code:\r
+ Device(COM0) {}\r
+\r
+ @param [in] NameString The new Device's name.\r
+ Must be a NULL-terminated ASL NameString\r
+ e.g.: "DEV0", "DV15.DEV0", etc.\r
+ The input string is copied.\r
+ @param [in] ParentNode If provided, set ParentNode as the parent\r
+ of the node created.\r
+ @param [out] NewObjectNode If success, contains the created node.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenDevice (\r
+ IN CONST CHAR8 * NameString,\r
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL\r
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ AML_OBJECT_NODE * ObjectNode;\r
+ AML_DATA_NODE * DataNode;\r
+ CHAR8 * AmlNameString;\r
+ UINT32 AmlNameStringSize;\r
+\r
+ if ((NameString == NULL) ||\r
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ObjectNode = NULL;\r
+ DataNode = NULL;\r
+ AmlNameString = NULL;\r
+\r
+ Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler1;\r
+ }\r
+\r
+ Status = AmlCreateObjectNode (\r
+ AmlGetByteEncodingByOpCode (AML_EXT_OP, AML_EXT_DEVICE_OP),\r
+ AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),\r
+ &ObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler1;\r
+ }\r
+\r
+ Status = AmlCreateDataNode (\r
+ EAmlNodeDataTypeNameString,\r
+ (UINT8*)AmlNameString,\r
+ AmlNameStringSize,\r
+ &DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler2;\r
+ }\r
+\r
+ Status = AmlSetFixedArgument (\r
+ ObjectNode,\r
+ EAmlParseIndexTerm0,\r
+ (AML_NODE_HEADER*)DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
+ goto error_handler2;\r
+ }\r
+\r
+ Status = LinkNode (\r
+ ObjectNode,\r
+ ParentNode,\r
+ NewObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler2;\r
+ }\r
+\r
+ // Free AmlNameString before returning as it is copied\r
+ // in the call to AmlCreateDataNode().\r
+ goto error_handler1;\r
+\r
+error_handler2:\r
+ if (ObjectNode != NULL) {\r
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
+ }\r
+\r
+error_handler1:\r
+ if (AmlNameString != NULL) {\r
+ FreePool (AmlNameString);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/** AML code generation for a Scope object node.\r
+\r
+ AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is\r
+ equivalent of the following ASL code:\r
+ Scope(_SB) {}\r
+\r
+ @param [in] NameString The new Scope's name.\r
+ Must be a NULL-terminated ASL NameString\r
+ e.g.: "DEV0", "DV15.DEV0", etc.\r
+ The input string is copied.\r
+ @param [in] ParentNode If provided, set ParentNode as the parent\r
+ of the node created.\r
+ @param [out] NewObjectNode If success, contains the created node.\r
+\r
+ @retval EFI_SUCCESS Success.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlCodeGenScope (\r
+ IN CONST CHAR8 * NameString,\r
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL\r
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ AML_OBJECT_NODE * ObjectNode;\r
+ AML_DATA_NODE * DataNode;\r
+ CHAR8 * AmlNameString;\r
+ UINT32 AmlNameStringSize;\r
+\r
+ if ((NameString == NULL) ||\r
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {\r
+ ASSERT (0);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ObjectNode = NULL;\r
+ DataNode = NULL;\r
+ AmlNameString = NULL;\r
+\r
+ Status = ConvertAslNameToAmlName (NameString, &AmlNameString);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ return Status;\r
+ }\r
+\r
+ Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler1;\r
+ }\r
+\r
+ Status = AmlCreateObjectNode (\r
+ AmlGetByteEncodingByOpCode (AML_SCOPE_OP, 0),\r
+ AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),\r
+ &ObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler1;\r
+ }\r
+\r
+ Status = AmlCreateDataNode (\r
+ EAmlNodeDataTypeNameString,\r
+ (UINT8*)AmlNameString,\r
+ AmlNameStringSize,\r
+ &DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler2;\r
+ }\r
+\r
+ Status = AmlSetFixedArgument (\r
+ ObjectNode,\r
+ EAmlParseIndexTerm0,\r
+ (AML_NODE_HEADER*)DataNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);\r
+ goto error_handler2;\r
+ }\r
+\r
+ Status = LinkNode (\r
+ ObjectNode,\r
+ ParentNode,\r
+ NewObjectNode\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ASSERT (0);\r
+ goto error_handler2;\r
+ }\r
+\r
+ // Free AmlNameString before returning as it is copied\r
+ // in the call to AmlCreateDataNode().\r
+ goto error_handler1;\r
+\r
+error_handler2:\r
+ if (ObjectNode != NULL) {\r
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);\r
+ }\r
+\r
+error_handler1:\r
+ if (AmlNameString != NULL) {\r
+ FreePool (AmlNameString);\r
+ }\r
+\r
+ return Status;\r
+}\r