4 Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <AmlNodeDefines.h>
11 #include <AcpiTableGenerator.h>
13 #include <AmlCoreInterface.h>
14 #include <AmlEncoding/Aml.h>
15 #include <Api/AmlApiHelper.h>
16 #include <CodeGen/AmlResourceDataCodeGen.h>
17 #include <Tree/AmlNode.h>
18 #include <Tree/AmlTree.h>
19 #include <String/AmlString.h>
20 #include <Utils/AmlUtility.h>
22 /** Utility function to link a node when returning from a CodeGen function.
24 @param [in] Node Newly created node.
25 @param [in] ParentNode If provided, set ParentNode as the parent
27 @param [out] NewObjectNode If not NULL:
28 - and Success, contains the created Node.
29 - and Error, reset to NULL.
31 @retval EFI_SUCCESS The function completed successfully.
32 @retval EFI_INVALID_PARAMETER Invalid parameter.
38 IN AML_OBJECT_NODE
* Node
,
39 IN AML_NODE_HEADER
* ParentNode
,
40 OUT AML_OBJECT_NODE
** NewObjectNode
45 if (NewObjectNode
!= NULL
) {
46 *NewObjectNode
= NULL
;
49 // Add RdNode as the last element.
50 if (ParentNode
!= NULL
) {
51 Status
= AmlVarListAddTail (ParentNode
, (AML_NODE_HEADER
*)Node
);
52 if (EFI_ERROR (Status
)) {
58 if (NewObjectNode
!= NULL
) {
59 *NewObjectNode
= Node
;
65 /** AML code generation for DefinitionBlock.
67 Create a Root Node handle.
68 It is the caller's responsibility to free the allocated memory
69 with the AmlDeleteTree function.
71 AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
72 equivalent to the following ASL code:
73 DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
74 OemID, TableID, OEMRevision) {}
75 with the ComplianceRevision set to 2 and the AMLFileName is ignored.
77 @param[in] TableSignature 4-character ACPI signature.
78 Must be 'DSDT' or 'SSDT'.
79 @param[in] OemId 6-character string OEM identifier.
80 @param[in] OemTableId 8-character string OEM table identifier.
81 @param[in] OemRevision OEM revision number.
82 @param[out] NewRootNode Pointer to the root node representing a
85 @retval EFI_SUCCESS Success.
86 @retval EFI_INVALID_PARAMETER Invalid parameter.
87 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
91 AmlCodeGenDefinitionBlock (
92 IN CONST CHAR8
* TableSignature
,
93 IN CONST CHAR8
* OemId
,
94 IN CONST CHAR8
* OemTableId
,
95 IN UINT32 OemRevision
,
96 OUT AML_ROOT_NODE
** NewRootNode
100 EFI_ACPI_DESCRIPTION_HEADER AcpiHeader
;
102 if ((TableSignature
== NULL
) ||
104 (OemTableId
== NULL
) ||
105 (NewRootNode
== NULL
)) {
107 return EFI_INVALID_PARAMETER
;
110 CopyMem (&AcpiHeader
.Signature
, TableSignature
, 4);
111 AcpiHeader
.Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
112 AcpiHeader
.Revision
= 2;
113 CopyMem (&AcpiHeader
.OemId
, OemId
, 6);
114 CopyMem (&AcpiHeader
.OemTableId
, OemTableId
, 8);
115 AcpiHeader
.OemRevision
= OemRevision
;
116 AcpiHeader
.CreatorId
= TABLE_GENERATOR_CREATOR_ID_ARM
;
117 AcpiHeader
.CreatorRevision
= CREATE_REVISION (1, 0);
119 Status
= AmlCreateRootNode (&AcpiHeader
, NewRootNode
);
120 ASSERT_EFI_ERROR (Status
);
125 /** AML code generation for a String object node.
127 @param [in] String Pointer to a NULL terminated string.
128 @param [out] NewObjectNode If success, contains the created
131 @retval EFI_SUCCESS Success.
132 @retval EFI_INVALID_PARAMETER Invalid parameter.
133 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
140 OUT AML_OBJECT_NODE
** NewObjectNode
144 AML_OBJECT_NODE
* ObjectNode
;
145 AML_DATA_NODE
* DataNode
;
147 if ((String
== NULL
) ||
148 (NewObjectNode
== NULL
)) {
150 return EFI_INVALID_PARAMETER
;
155 Status
= AmlCreateObjectNode (
156 AmlGetByteEncodingByOpCode (AML_STRING_PREFIX
, 0),
160 if (EFI_ERROR (Status
)) {
165 Status
= AmlCreateDataNode (
166 EAmlNodeDataTypeString
,
168 (UINT32
)AsciiStrLen (String
) + 1,
171 if (EFI_ERROR (Status
)) {
176 Status
= AmlSetFixedArgument (
179 (AML_NODE_HEADER
*)DataNode
181 if (EFI_ERROR (Status
)) {
183 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
187 *NewObjectNode
= ObjectNode
;
191 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
195 /** AML code generation for an Integer object node.
197 @param [in] Integer Integer of the Integer object node.
198 @param [out] NewObjectNode If success, contains the created
201 @retval EFI_SUCCESS Success.
202 @retval EFI_INVALID_PARAMETER Invalid parameter.
203 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
210 OUT AML_OBJECT_NODE
** NewObjectNode
216 if (NewObjectNode
== NULL
) {
218 return EFI_INVALID_PARAMETER
;
221 // Create an object node containing Zero.
222 Status
= AmlCreateObjectNode (
223 AmlGetByteEncodingByOpCode (AML_ZERO_OP
, 0),
227 if (EFI_ERROR (Status
)) {
232 // Update the object node with integer value.
233 Status
= AmlNodeSetIntegerValue (*NewObjectNode
, Integer
, &ValueWidthDiff
);
234 if (EFI_ERROR (Status
)) {
236 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
242 /** AML code generation for a Package object node.
244 The package generated is empty. New elements can be added via its
245 list of variable arguments.
247 @param [out] NewObjectNode If success, contains the created
250 @retval EFI_SUCCESS Success.
251 @retval EFI_INVALID_PARAMETER Invalid parameter.
252 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
258 OUT AML_OBJECT_NODE
** NewObjectNode
262 AML_DATA_NODE
* DataNode
;
265 if (NewObjectNode
== NULL
) {
267 return EFI_INVALID_PARAMETER
;
272 // Create an object node.
274 // - one byte to store the PkgLength
275 // - one byte for the NumElements.
276 // Cf ACPI6.3, s20.2.5 "Term Objects Encoding"
277 // DefPackage := PackageOp PkgLength NumElements PackageElementList
278 // NumElements := ByteData
279 Status
= AmlCreateObjectNode (
280 AmlGetByteEncodingByOpCode (AML_PACKAGE_OP
, 0),
284 if (EFI_ERROR (Status
)) {
289 // NumElements is a ByteData.
290 Status
= AmlCreateDataNode (
291 EAmlNodeDataTypeUInt
,
296 if (EFI_ERROR (Status
)) {
301 Status
= AmlSetFixedArgument (
304 (AML_NODE_HEADER
*)DataNode
306 if (EFI_ERROR (Status
)) {
314 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
315 if (DataNode
!= NULL
) {
316 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
321 /** AML code generation for a Buffer object node.
323 To create a Buffer object node with an empty buffer,
324 call the function with (Buffer=NULL, BufferSize=0).
326 @param [in] Buffer Buffer to set for the created Buffer
327 object node. The Buffer's content is copied.
328 NULL if there is no buffer to set for
330 @param [in] BufferSize Size of the Buffer.
331 0 if there is no buffer to set for
333 @param [out] NewObjectNode If success, contains the created
336 @retval EFI_SUCCESS Success.
337 @retval EFI_INVALID_PARAMETER Invalid parameter.
338 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
344 IN CONST UINT8
* Buffer OPTIONAL
,
345 IN UINT32 BufferSize OPTIONAL
,
346 OUT AML_OBJECT_NODE
** NewObjectNode
350 AML_OBJECT_NODE
* BufferNode
;
351 AML_OBJECT_NODE
* BufferSizeNode
;
352 UINT32 BufferSizeNodeSize
;
353 AML_DATA_NODE
* DataNode
;
356 // Buffer and BufferSize must be either both set, or both clear.
357 if ((NewObjectNode
== NULL
) ||
358 ((Buffer
== NULL
) != (BufferSize
== 0))) {
360 return EFI_INVALID_PARAMETER
;
366 // Cf ACPI 6.3 specification, s20.2.5.4 "Type 2 Opcodes Encoding"
367 // DefBuffer := BufferOp PkgLength BufferSize ByteList
369 // BufferSize := TermArg => Integer
371 Status
= AmlCodeGenInteger (BufferSize
, &BufferSizeNode
);
372 if (EFI_ERROR (Status
)) {
377 // Get the number of bytes required to encode the BufferSizeNode.
378 Status
= AmlComputeSize (
379 (AML_NODE_HEADER
*)BufferSizeNode
,
382 if (EFI_ERROR (Status
)) {
387 // Compute the size to write in the PkgLen.
388 Status
= AmlComputePkgLength (BufferSizeNodeSize
+ BufferSize
, &PkgLen
);
389 if (EFI_ERROR (Status
)) {
394 // Create an object node for the buffer.
395 Status
= AmlCreateObjectNode (
396 AmlGetByteEncodingByOpCode (AML_BUFFER_OP
, 0),
400 if (EFI_ERROR (Status
)) {
405 // Set the BufferSizeNode as a fixed argument of the BufferNode.
406 Status
= AmlSetFixedArgument (
409 (AML_NODE_HEADER
*)BufferSizeNode
411 if (EFI_ERROR (Status
)) {
416 // BufferSizeNode is now attached.
417 BufferSizeNode
= NULL
;
419 // If there is a buffer, create a DataNode and attach it to the BufferNode.
420 if (Buffer
!= NULL
) {
421 Status
= AmlCreateDataNode (
427 if (EFI_ERROR (Status
)) {
432 Status
= AmlVarListAddTail (
433 (AML_NODE_HEADER
*)BufferNode
,
434 (AML_NODE_HEADER
*)DataNode
436 if (EFI_ERROR (Status
)) {
442 *NewObjectNode
= BufferNode
;
446 if (BufferSizeNode
!= NULL
) {
447 AmlDeleteTree ((AML_NODE_HEADER
*)BufferSizeNode
);
449 if (BufferNode
!= NULL
) {
450 AmlDeleteTree ((AML_NODE_HEADER
*)BufferNode
);
452 if (DataNode
!= NULL
) {
453 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
458 /** AML code generation for a ResourceTemplate.
460 "ResourceTemplate" is a macro defined in ACPI 6.3, s19.3.3
461 "ASL Resource Templates". It allows to store resource data elements.
463 In AML, a ResourceTemplate is implemented as a Buffer storing resource
464 data elements. An EndTag resource data descriptor must be at the end
465 of the list of resource data elements.
466 This function generates a Buffer node with an EndTag resource data
467 descriptor. It can be seen as an empty list of resource data elements.
469 @param [out] NewObjectNode If success, contains the created
470 ResourceTemplate object node.
472 @retval EFI_SUCCESS Success.
473 @retval EFI_INVALID_PARAMETER Invalid parameter.
474 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
479 AmlCodeGenResourceTemplate (
480 OUT AML_OBJECT_NODE
** NewObjectNode
484 AML_OBJECT_NODE
* BufferNode
;
486 if (NewObjectNode
== NULL
) {
488 return EFI_INVALID_PARAMETER
;
491 // Create a BufferNode with an empty buffer.
492 Status
= AmlCodeGenBuffer (NULL
, 0, &BufferNode
);
493 if (EFI_ERROR (Status
)) {
498 // Create an EndTag resource data element and attach it to the Buffer.
499 Status
= AmlCodeGenEndTag (0, BufferNode
, NULL
);
500 if (EFI_ERROR (Status
)) {
502 AmlDeleteTree ((AML_NODE_HEADER
*)BufferNode
);
506 *NewObjectNode
= BufferNode
;
510 /** AML code generation for a Name object node.
512 @param [in] NameString The new variable name.
513 Must be a NULL-terminated ASL NameString
514 e.g.: "DEV0", "DV15.DEV0", etc.
515 This input string is copied.
516 @param [in] Object Object associated to the NameString.
517 @param [in] ParentNode If provided, set ParentNode as the parent
519 @param [out] NewObjectNode If success, contains the created node.
521 @retval EFI_SUCCESS Success.
522 @retval EFI_INVALID_PARAMETER Invalid parameter.
523 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
529 IN CONST CHAR8
* NameString
,
530 IN AML_OBJECT_NODE
* Object
,
531 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
532 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
536 AML_OBJECT_NODE
* ObjectNode
;
537 AML_DATA_NODE
* DataNode
;
538 CHAR8
* AmlNameString
;
539 UINT32 AmlNameStringSize
;
541 if ((NameString
== NULL
) ||
543 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
545 return EFI_INVALID_PARAMETER
;
550 AmlNameString
= NULL
;
552 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
553 if (EFI_ERROR (Status
)) {
558 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
559 if (EFI_ERROR (Status
)) {
564 Status
= AmlCreateObjectNode (
565 AmlGetByteEncodingByOpCode (AML_NAME_OP
, 0),
569 if (EFI_ERROR (Status
)) {
574 Status
= AmlCreateDataNode (
575 EAmlNodeDataTypeNameString
,
576 (UINT8
*)AmlNameString
,
580 if (EFI_ERROR (Status
)) {
585 Status
= AmlSetFixedArgument (
588 (AML_NODE_HEADER
*)DataNode
590 if (EFI_ERROR (Status
)) {
592 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
596 Status
= AmlSetFixedArgument (
599 (AML_NODE_HEADER
*)Object
601 if (EFI_ERROR (Status
)) {
611 if (EFI_ERROR (Status
)) {
616 // Free AmlNameString before returning as it is copied
617 // in the call to AmlCreateDataNode().
621 if (ObjectNode
!= NULL
) {
622 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
626 if (AmlNameString
!= NULL
) {
627 FreePool (AmlNameString
);
633 /** AML code generation for a Name object node, containing a String.
635 AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
636 equivalent of the following ASL code:
637 Name(_HID, "HID0000")
639 @param [in] NameString The new variable name.
640 Must be a NULL-terminated ASL NameString
641 e.g.: "DEV0", "DV15.DEV0", etc.
642 The input string is copied.
643 @param [in] String NULL terminated String to associate to the
645 @param [in] ParentNode If provided, set ParentNode as the parent
647 @param [out] NewObjectNode If success, contains the created node.
649 @retval EFI_SUCCESS Success.
650 @retval EFI_INVALID_PARAMETER Invalid parameter.
651 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
655 AmlCodeGenNameString (
656 IN CONST CHAR8
* NameString
,
658 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
659 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
663 AML_OBJECT_NODE
* ObjectNode
;
665 if ((NameString
== NULL
) ||
667 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
669 return EFI_INVALID_PARAMETER
;
672 Status
= AmlCodeGenString (String
, &ObjectNode
);
673 if (EFI_ERROR (Status
)) {
678 Status
= AmlCodeGenName (
684 if (EFI_ERROR (Status
)) {
686 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
692 /** AML code generation for a Name object node, containing an Integer.
694 AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
695 equivalent of the following ASL code:
698 @param [in] NameString The new variable name.
699 Must be a NULL-terminated ASL NameString
700 e.g.: "DEV0", "DV15.DEV0", etc.
701 The input string is copied.
702 @param [in] Integer Integer to associate to the NameString.
703 @param [in] ParentNode If provided, set ParentNode as the parent
705 @param [out] NewObjectNode If success, contains the created node.
707 @retval EFI_SUCCESS Success.
708 @retval EFI_INVALID_PARAMETER Invalid parameter.
709 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
713 AmlCodeGenNameInteger (
714 IN CONST CHAR8
* NameString
,
716 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
717 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
721 AML_OBJECT_NODE
* ObjectNode
;
723 if ((NameString
== NULL
) ||
724 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
726 return EFI_INVALID_PARAMETER
;
729 Status
= AmlCodeGenInteger (Integer
, &ObjectNode
);
730 if (EFI_ERROR (Status
)) {
735 Status
= AmlCodeGenName (
741 if (EFI_ERROR (Status
)) {
743 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
749 /** AML code generation for a Device object node.
751 AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
752 equivalent of the following ASL code:
755 @param [in] NameString The new Device's name.
756 Must be a NULL-terminated ASL NameString
757 e.g.: "DEV0", "DV15.DEV0", etc.
758 The input string is copied.
759 @param [in] ParentNode If provided, set ParentNode as the parent
761 @param [out] NewObjectNode If success, contains the created node.
763 @retval EFI_SUCCESS Success.
764 @retval EFI_INVALID_PARAMETER Invalid parameter.
765 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
770 IN CONST CHAR8
* NameString
,
771 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
772 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
776 AML_OBJECT_NODE
* ObjectNode
;
777 AML_DATA_NODE
* DataNode
;
778 CHAR8
* AmlNameString
;
779 UINT32 AmlNameStringSize
;
781 if ((NameString
== NULL
) ||
782 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
784 return EFI_INVALID_PARAMETER
;
789 AmlNameString
= NULL
;
791 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
792 if (EFI_ERROR (Status
)) {
797 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
798 if (EFI_ERROR (Status
)) {
803 Status
= AmlCreateObjectNode (
804 AmlGetByteEncodingByOpCode (AML_EXT_OP
, AML_EXT_DEVICE_OP
),
805 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
808 if (EFI_ERROR (Status
)) {
813 Status
= AmlCreateDataNode (
814 EAmlNodeDataTypeNameString
,
815 (UINT8
*)AmlNameString
,
819 if (EFI_ERROR (Status
)) {
824 Status
= AmlSetFixedArgument (
827 (AML_NODE_HEADER
*)DataNode
829 if (EFI_ERROR (Status
)) {
831 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
840 if (EFI_ERROR (Status
)) {
845 // Free AmlNameString before returning as it is copied
846 // in the call to AmlCreateDataNode().
850 if (ObjectNode
!= NULL
) {
851 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
855 if (AmlNameString
!= NULL
) {
856 FreePool (AmlNameString
);
862 /** AML code generation for a Scope object node.
864 AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
865 equivalent of the following ASL code:
868 @param [in] NameString The new Scope's name.
869 Must be a NULL-terminated ASL NameString
870 e.g.: "DEV0", "DV15.DEV0", etc.
871 The input string is copied.
872 @param [in] ParentNode If provided, set ParentNode as the parent
874 @param [out] NewObjectNode If success, contains the created node.
876 @retval EFI_SUCCESS Success.
877 @retval EFI_INVALID_PARAMETER Invalid parameter.
878 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
883 IN CONST CHAR8
* NameString
,
884 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
885 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
889 AML_OBJECT_NODE
* ObjectNode
;
890 AML_DATA_NODE
* DataNode
;
891 CHAR8
* AmlNameString
;
892 UINT32 AmlNameStringSize
;
894 if ((NameString
== NULL
) ||
895 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
897 return EFI_INVALID_PARAMETER
;
902 AmlNameString
= NULL
;
904 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
905 if (EFI_ERROR (Status
)) {
910 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
911 if (EFI_ERROR (Status
)) {
916 Status
= AmlCreateObjectNode (
917 AmlGetByteEncodingByOpCode (AML_SCOPE_OP
, 0),
918 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
921 if (EFI_ERROR (Status
)) {
926 Status
= AmlCreateDataNode (
927 EAmlNodeDataTypeNameString
,
928 (UINT8
*)AmlNameString
,
932 if (EFI_ERROR (Status
)) {
937 Status
= AmlSetFixedArgument (
940 (AML_NODE_HEADER
*)DataNode
942 if (EFI_ERROR (Status
)) {
944 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
953 if (EFI_ERROR (Status
)) {
958 // Free AmlNameString before returning as it is copied
959 // in the call to AmlCreateDataNode().
963 if (ObjectNode
!= NULL
) {
964 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
968 if (AmlNameString
!= NULL
) {
969 FreePool (AmlNameString
);
975 /** AML code generation for a Method object node.
977 AmlCodeGenMethod ("MET0", 1, TRUE, 3, ParentNode, NewObjectNode) is
978 equivalent of the following ASL code:
979 Method(MET0, 1, Serialized, 3) {}
981 ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
982 DefMethod := MethodOp PkgLength NameString MethodFlags TermList
985 The ASL parameters "ReturnType" and "ParameterTypes" are not asked
986 in this function. They are optional parameters in ASL.
988 @param [in] NameString The new Method's name.
989 Must be a NULL-terminated ASL NameString
990 e.g.: "MET0", "_SB.MET0", etc.
991 The input string is copied.
992 @param [in] NumArgs Number of arguments.
993 Must be 0 <= NumArgs <= 6.
994 @param [in] IsSerialized TRUE is equivalent to Serialized.
995 FALSE is equivalent to NotSerialized.
996 Default is NotSerialized in ASL spec.
997 @param [in] SyncLevel Synchronization level for the method.
998 Must be 0 <= SyncLevel <= 15.
1000 @param [in] ParentNode If provided, set ParentNode as the parent
1001 of the node created.
1002 @param [out] NewObjectNode If success, contains the created node.
1004 @retval EFI_SUCCESS Success.
1005 @retval EFI_INVALID_PARAMETER Invalid parameter.
1006 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1012 IN CONST CHAR8
* NameString
,
1014 IN BOOLEAN IsSerialized
,
1016 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
1017 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
1023 AML_OBJECT_NODE
* ObjectNode
;
1024 AML_DATA_NODE
* DataNode
;
1025 CHAR8
* AmlNameString
;
1026 UINT32 AmlNameStringSize
;
1028 if ((NameString
== NULL
) ||
1031 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
1033 return EFI_INVALID_PARAMETER
;
1039 // ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
1040 // DefMethod := MethodOp PkgLength NameString MethodFlags TermList
1043 // 1- Create the NameString
1044 // 2- Compute the size to write in the PkgLen
1045 // 3- Create nodes for the NameString and Method object node
1046 // 4- Set the NameString DataNode as a fixed argument
1047 // 5- Create and link the MethodFlags node
1049 // 1- Create the NameString
1050 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1051 if (EFI_ERROR (Status
)) {
1056 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1057 if (EFI_ERROR (Status
)) {
1059 goto error_handler1
;
1062 // 2- Compute the size to write in the PkgLen
1063 // Add 1 byte (ByteData) for MethodFlags.
1064 Status
= AmlComputePkgLength (AmlNameStringSize
+ 1, &PkgLen
);
1065 if (EFI_ERROR (Status
)) {
1067 goto error_handler1
;
1070 // 3- Create nodes for the NameString and Method object node
1071 Status
= AmlCreateObjectNode (
1072 AmlGetByteEncodingByOpCode (AML_METHOD_OP
, 0),
1076 if (EFI_ERROR (Status
)) {
1078 goto error_handler1
;
1081 Status
= AmlCreateDataNode (
1082 EAmlNodeDataTypeNameString
,
1083 (UINT8
*)AmlNameString
,
1087 if (EFI_ERROR (Status
)) {
1089 goto error_handler2
;
1092 // 4- Set the NameString DataNode as a fixed argument
1093 Status
= AmlSetFixedArgument (
1095 EAmlParseIndexTerm0
,
1096 (AML_NODE_HEADER
*)DataNode
1098 if (EFI_ERROR (Status
)) {
1100 goto error_handler2
;
1105 // 5- Create and link the MethodFlags node
1107 (IsSerialized
? BIT3
: 0) |
1110 Status
= AmlCreateDataNode (EAmlNodeDataTypeUInt
, &Flags
, 1, &DataNode
);
1111 if (EFI_ERROR (Status
)) {
1113 goto error_handler2
;
1116 Status
= AmlSetFixedArgument (
1118 EAmlParseIndexTerm1
,
1119 (AML_NODE_HEADER
*)DataNode
1121 if (EFI_ERROR (Status
)) {
1123 goto error_handler2
;
1126 // Data node is attached so set the pointer to
1127 // NULL to ensure correct error handling.
1135 if (EFI_ERROR (Status
)) {
1137 goto error_handler2
;
1140 // Free AmlNameString before returning as it is copied
1141 // in the call to AmlCreateDataNode().
1142 goto error_handler1
;
1145 if (ObjectNode
!= NULL
) {
1146 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1148 if (DataNode
!= NULL
) {
1149 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
1153 if (AmlNameString
!= NULL
) {
1154 FreePool (AmlNameString
);
1159 /** AML code generation for a Return object node.
1161 AmlCodeGenReturn (ReturnNode, ParentNode, NewObjectNode) is
1162 equivalent of the following ASL code:
1163 Return([Content of the ReturnNode])
1165 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:
1166 DefReturn := ReturnOp ArgObject
1168 ArgObject := TermArg => DataRefObject
1170 Thus, the ReturnNode must be evaluated as a DataRefObject. It can
1171 be a NameString referencing an object. As this CodeGen Api doesn't
1172 do semantic checking, it is strongly advised to check the AML bytecode
1173 generated by this function against an ASL compiler.
1175 The ReturnNode must be generated inside a Method body scope.
1177 @param [in] ReturnNode The object returned by the Return ASL statement.
1178 This node is deleted if an error occurs.
1179 @param [in] ParentNode If provided, set ParentNode as the parent
1180 of the node created.
1181 Must be a MethodOp node.
1182 @param [out] NewObjectNode If success, contains the created node.
1184 @retval EFI_SUCCESS Success.
1185 @retval EFI_INVALID_PARAMETER Invalid parameter.
1186 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1192 IN AML_NODE_HEADER
* ReturnNode
,
1193 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
1194 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
1198 AML_OBJECT_NODE
* ObjectNode
;
1200 if ((ReturnNode
== NULL
) ||
1201 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)) ||
1202 ((ParentNode
!= NULL
) &&
1203 !AmlNodeCompareOpCode (
1204 (AML_OBJECT_NODE
*)ParentNode
, AML_METHOD_OP
, 0))) {
1206 return EFI_INVALID_PARAMETER
;
1209 Status
= AmlCreateObjectNode (
1210 AmlGetByteEncodingByOpCode (AML_RETURN_OP
, 0),
1214 if (EFI_ERROR (Status
)) {
1219 Status
= AmlSetFixedArgument (
1221 EAmlParseIndexTerm0
,
1222 (AML_NODE_HEADER
*)ReturnNode
1224 if (EFI_ERROR (Status
)) {
1236 if (EFI_ERROR (Status
)) {
1244 if (ReturnNode
!= NULL
) {
1245 AmlDeleteTree (ReturnNode
);
1247 if (ObjectNode
!= NULL
) {
1248 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1253 /** AML code generation for a Return object node,
1254 returning the object as an input NameString.
1256 AmlCodeGenReturn ("NAM1", ParentNode, NewObjectNode) is
1257 equivalent of the following ASL code:
1260 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:
1261 DefReturn := ReturnOp ArgObject
1263 ArgObject := TermArg => DataRefObject
1265 Thus, the ReturnNode must be evaluated as a DataRefObject. It can
1266 be a NameString referencing an object. As this CodeGen Api doesn't
1267 do semantic checking, it is strongly advised to check the AML bytecode
1268 generated by this function against an ASL compiler.
1270 The ReturnNode must be generated inside a Method body scope.
1272 @param [in] NameString The object referenced by this NameString
1273 is returned by the Return ASL statement.
1274 Must be a NULL-terminated ASL NameString
1275 e.g.: "NAM1", "_SB.NAM1", etc.
1276 The input string is copied.
1277 @param [in] ParentNode If provided, set ParentNode as the parent
1278 of the node created.
1279 Must be a MethodOp node.
1280 @param [out] NewObjectNode If success, contains the created node.
1282 @retval EFI_SUCCESS Success.
1283 @retval EFI_INVALID_PARAMETER Invalid parameter.
1284 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1289 AmlCodeGenReturnNameString (
1290 IN CONST CHAR8
* NameString
,
1291 IN AML_NODE_HEADER
* ParentNode OPTIONAL
,
1292 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
1296 AML_DATA_NODE
* DataNode
;
1297 CHAR8
* AmlNameString
;
1298 UINT32 AmlNameStringSize
;
1302 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1303 if (EFI_ERROR (Status
)) {
1308 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1309 if (EFI_ERROR (Status
)) {
1314 Status
= AmlCreateDataNode (
1315 EAmlNodeDataTypeNameString
,
1316 (UINT8
*)AmlNameString
,
1320 if (EFI_ERROR (Status
)) {
1325 // AmlCodeGenReturn() deletes DataNode if error.
1326 Status
= AmlCodeGenReturn (
1327 (AML_NODE_HEADER
*)DataNode
,
1331 ASSERT_EFI_ERROR (Status
);
1334 if (AmlNameString
!= NULL
) {
1335 FreePool (AmlNameString
);
1340 /** AML code generation for a method returning a NameString.
1342 AmlCodeGenMethodRetNameString (
1343 "MET0", "_CRS", 1, TRUE, 3, ParentNode, NewObjectNode
1345 is equivalent of the following ASL code:
1346 Method(MET0, 1, Serialized, 3) {
1350 The ASL parameters "ReturnType" and "ParameterTypes" are not asked
1351 in this function. They are optional parameters in ASL.
1353 @param [in] MethodNameString The new Method's name.
1354 Must be a NULL-terminated ASL NameString
1355 e.g.: "MET0", "_SB.MET0", etc.
1356 The input string is copied.
1357 @param [in] ReturnedNameString The name of the object returned by the
1358 method. Optional parameter, can be:
1360 - A NULL-terminated ASL NameString.
1361 e.g.: "MET0", "_SB.MET0", etc.
1362 The input string is copied.
1363 @param [in] NumArgs Number of arguments.
1364 Must be 0 <= NumArgs <= 6.
1365 @param [in] IsSerialized TRUE is equivalent to Serialized.
1366 FALSE is equivalent to NotSerialized.
1367 Default is NotSerialized in ASL spec.
1368 @param [in] SyncLevel Synchronization level for the method.
1369 Must be 0 <= SyncLevel <= 15.
1370 Default is 0 in ASL.
1371 @param [in] ParentNode If provided, set ParentNode as the parent
1372 of the node created.
1373 @param [out] NewObjectNode If success, contains the created node.
1375 @retval EFI_SUCCESS Success.
1376 @retval EFI_INVALID_PARAMETER Invalid parameter.
1377 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1381 AmlCodeGenMethodRetNameString (
1382 IN CONST CHAR8
* MethodNameString
,
1383 IN CONST CHAR8
* ReturnedNameString OPTIONAL
,
1385 IN BOOLEAN IsSerialized
,
1387 IN AML_NODE_HANDLE ParentNode OPTIONAL
,
1388 OUT AML_OBJECT_NODE_HANDLE
* NewObjectNode OPTIONAL
1392 AML_OBJECT_NODE_HANDLE MethodNode
;
1394 if ((MethodNameString
== NULL
) ||
1395 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
1397 return EFI_INVALID_PARAMETER
;
1400 // Create a Method named MethodNameString.
1401 Status
= AmlCodeGenMethod (
1409 if (EFI_ERROR (Status
)) {
1414 // Return ReturnedNameString if provided.
1415 if (ReturnedNameString
!= NULL
) {
1416 Status
= AmlCodeGenReturnNameString (
1418 (AML_NODE_HANDLE
)MethodNode
,
1421 if (EFI_ERROR (Status
)) {
1432 if (EFI_ERROR (Status
)) {
1440 if (MethodNode
!= NULL
) {
1441 AmlDeleteTree ((AML_NODE_HANDLE
)MethodNode
);
1446 /** Create a _LPI name.
1448 AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is
1449 equivalent of the following ASL code:
1450 Name (_LPI, Package (
1456 This function doesn't define any LPI state. As shown above, the count
1457 of _LPI state is set to 0.
1458 The AmlAddLpiState () function allows to add LPI states.
1460 Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
1462 @param [in] LpiNameString The new LPI 's object name.
1463 Must be a NULL-terminated ASL NameString
1464 e.g.: "_LPI", "DEV0.PLPI", etc.
1465 The input string is copied.
1466 @param [in] Revision Revision number of the _LPI states.
1467 @param [in] LevelId A platform defined number that identifies the
1468 level of hierarchy of the processor node to
1469 which the LPI states apply.
1470 @param [in] ParentNode If provided, set ParentNode as the parent
1471 of the node created.
1472 @param [out] NewLpiNode If success, contains the created node.
1474 @retval EFI_SUCCESS The function completed successfully.
1475 @retval EFI_INVALID_PARAMETER Invalid parameter.
1476 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1481 IN CONST CHAR8
* LpiNameString
,
1484 IN AML_NODE_HANDLE ParentNode OPTIONAL
,
1485 OUT AML_OBJECT_NODE_HANDLE
* NewLpiNode OPTIONAL
1489 AML_OBJECT_NODE_HANDLE PackageNode
;
1490 AML_OBJECT_NODE_HANDLE IntegerNode
;
1492 if ((LpiNameString
== NULL
) ||
1493 ((ParentNode
== NULL
) && (NewLpiNode
== NULL
))) {
1495 return EFI_INVALID_PARAMETER
;
1500 Status
= AmlCodeGenPackage (&PackageNode
);
1501 if (EFI_ERROR (Status
)) {
1506 // Create and attach Revision
1507 Status
= AmlCodeGenInteger (Revision
, &IntegerNode
);
1508 if (EFI_ERROR (Status
)) {
1514 Status
= AmlVarListAddTail (
1515 (AML_NODE_HANDLE
)PackageNode
,
1516 (AML_NODE_HANDLE
)IntegerNode
1518 if (EFI_ERROR (Status
)) {
1525 // Create and attach LevelId
1526 Status
= AmlCodeGenInteger (LevelId
, &IntegerNode
);
1527 if (EFI_ERROR (Status
)) {
1533 Status
= AmlVarListAddTail (
1534 (AML_NODE_HANDLE
)PackageNode
,
1535 (AML_NODE_HANDLE
)IntegerNode
1537 if (EFI_ERROR (Status
)) {
1544 // Create and attach Count. No LPI state is added, so 0.
1545 Status
= AmlCodeGenInteger (0, &IntegerNode
);
1546 if (EFI_ERROR (Status
)) {
1552 Status
= AmlVarListAddTail (
1553 (AML_NODE_HANDLE
)PackageNode
,
1554 (AML_NODE_HANDLE
)IntegerNode
1556 if (EFI_ERROR (Status
)) {
1563 Status
= AmlCodeGenName (LpiNameString
, PackageNode
, ParentNode
, NewLpiNode
);
1564 if (EFI_ERROR (Status
)) {
1572 AmlDeleteTree ((AML_NODE_HANDLE
)PackageNode
);
1573 if (IntegerNode
!= NULL
) {
1574 AmlDeleteTree ((AML_NODE_HANDLE
)IntegerNode
);
1579 /** Add an _LPI state to a LPI node created using AmlCreateLpiNode.
1581 AmlAddLpiState increments the Count of LPI states in the LPI node by one,
1582 and adds the following package:
1585 WorstCaseWakeLatency,
1590 (GenericRegisterDescriptor != NULL) ? // Entry method. If a
1591 ResourceTemplate(GenericRegisterDescriptor) : // Register is given,
1592 Integer, // use it. Use the
1593 // Integer otherwise.
1594 ResourceTemplate() { // NULL Residency Counter
1595 Register (SystemMemory, 0, 0, 0, 0)
1597 ResourceTemplate() { // NULL Usage Counter
1598 Register (SystemMemory, 0, 0, 0, 0)
1600 "" // NULL State Name
1603 Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
1605 @param [in] MinResidency Minimum Residency.
1606 @param [in] WorstCaseWakeLatency Worst case wake-up latency.
1607 @param [in] Flags Flags.
1608 @param [in] ArchFlags Architectural flags.
1609 @param [in] ResCntFreq Residency Counter Frequency.
1610 @param [in] EnableParentState Enabled Parent State.
1611 @param [in] GenericRegisterDescriptor Entry Method.
1612 If not NULL, use this Register to
1613 describe the entry method address.
1614 @param [in] Integer Entry Method.
1615 If GenericRegisterDescriptor is NULL,
1617 @param [in] ResidencyCounterRegister If not NULL, use it to populate the
1618 residency counter register.
1619 @param [in] UsageCounterRegister If not NULL, use it to populate the
1620 usage counter register.
1621 @param [in] StateName If not NULL, use it to populate the
1623 @param [in] LpiNode Lpi node created with the function
1624 AmlCreateLpiNode to which the new LPI
1627 @retval EFI_SUCCESS The function completed successfully.
1628 @retval EFI_INVALID_PARAMETER Invalid parameter.
1629 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1634 IN UINT32 MinResidency
,
1635 IN UINT32 WorstCaseWakeLatency
,
1637 IN UINT32 ArchFlags
,
1638 IN UINT32 ResCntFreq
,
1639 IN UINT32 EnableParentState
,
1640 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE
* GenericRegisterDescriptor OPTIONAL
,
1641 IN UINT64 Integer OPTIONAL
,
1642 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE
* ResidencyCounterRegister OPTIONAL
,
1643 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE
* UsageCounterRegister OPTIONAL
,
1644 IN CHAR8
* StateName OPTIONAL
,
1645 IN AML_OBJECT_NODE_HANDLE LpiNode
1649 AML_DATA_NODE_HANDLE RdNode
;
1650 AML_OBJECT_NODE_HANDLE PackageNode
;
1651 AML_OBJECT_NODE_HANDLE IntegerNode
;
1652 AML_OBJECT_NODE_HANDLE StringNode
;
1653 AML_OBJECT_NODE_HANDLE NewLpiPackageNode
;
1654 AML_OBJECT_NODE_HANDLE ResourceTemplateNode
;
1657 AML_OBJECT_NODE_HANDLE CountNode
;
1660 if ((LpiNode
== NULL
) ||
1661 (AmlGetNodeType ((AML_NODE_HANDLE
)LpiNode
) != EAmlNodeObject
) ||
1662 (!AmlNodeHasOpCode (LpiNode
, AML_NAME_OP
, 0))) {
1664 return EFI_INVALID_PARAMETER
;
1670 ResourceTemplateNode
= NULL
;
1672 // AmlCreateLpiNode () created a LPI container such as:
1673 // Name (_LPI, Package (
1678 // Get the LPI container, a PackageOp object node stored as the 2nd fixed
1679 // argument (i.e. index 1) of LpiNode.
1680 PackageNode
= (AML_OBJECT_NODE_HANDLE
)AmlGetFixedArgument (
1684 if ((PackageNode
== NULL
) ||
1685 (AmlGetNodeType ((AML_NODE_HANDLE
)PackageNode
) != EAmlNodeObject
) ||
1686 (!AmlNodeHasOpCode (PackageNode
, AML_PACKAGE_OP
, 0))) {
1688 return EFI_INVALID_PARAMETER
;
1692 // The third variable argument is the LPI Count node.
1693 for (Index
= 0; Index
< 3; Index
++) {
1694 CountNode
= (AML_OBJECT_NODE_HANDLE
)AmlGetNextVariableArgument (
1695 (AML_NODE_HANDLE
)PackageNode
,
1696 (AML_NODE_HANDLE
)CountNode
1698 if (CountNode
== NULL
) {
1700 return EFI_INVALID_PARAMETER
;
1704 Status
= AmlNodeGetIntegerValue (CountNode
, &Count
);
1705 if (EFI_ERROR (Status
)) {
1709 Status
= AmlUpdateInteger (CountNode
, Count
+ 1);
1710 if (EFI_ERROR (Status
)) {
1715 Status
= AmlCodeGenPackage (&NewLpiPackageNode
);
1716 if (EFI_ERROR (Status
)) {
1722 Status
= AmlCodeGenInteger (MinResidency
, &IntegerNode
);
1723 if (EFI_ERROR (Status
)) {
1728 Status
= AmlVarListAddTail (
1729 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1730 (AML_NODE_HANDLE
)IntegerNode
1732 if (EFI_ERROR (Status
)) {
1738 // WorstCaseWakeLatency
1739 Status
= AmlCodeGenInteger (WorstCaseWakeLatency
, &IntegerNode
);
1740 if (EFI_ERROR (Status
)) {
1745 Status
= AmlVarListAddTail (
1746 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1747 (AML_NODE_HANDLE
)IntegerNode
1749 if (EFI_ERROR (Status
)) {
1756 Status
= AmlCodeGenInteger (Flags
, &IntegerNode
);
1757 if (EFI_ERROR (Status
)) {
1762 Status
= AmlVarListAddTail (
1763 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1764 (AML_NODE_HANDLE
)IntegerNode
1766 if (EFI_ERROR (Status
)) {
1773 Status
= AmlCodeGenInteger (ArchFlags
, &IntegerNode
);
1774 if (EFI_ERROR (Status
)) {
1779 Status
= AmlVarListAddTail (
1780 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1781 (AML_NODE_HANDLE
)IntegerNode
1783 if (EFI_ERROR (Status
)) {
1790 Status
= AmlCodeGenInteger (ResCntFreq
, &IntegerNode
);
1791 if (EFI_ERROR (Status
)) {
1796 Status
= AmlVarListAddTail (
1797 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1798 (AML_NODE_HANDLE
)IntegerNode
1800 if (EFI_ERROR (Status
)) {
1806 // EnableParentState
1807 Status
= AmlCodeGenInteger (EnableParentState
, &IntegerNode
);
1808 if (EFI_ERROR (Status
)) {
1813 Status
= AmlVarListAddTail (
1814 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1815 (AML_NODE_HANDLE
)IntegerNode
1817 if (EFI_ERROR (Status
)) {
1824 if (GenericRegisterDescriptor
!= NULL
) {
1825 // Entry Method: As a Register resource data
1826 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
1827 if (EFI_ERROR (Status
)) {
1829 ResourceTemplateNode
= NULL
;
1832 Status
= AmlCodeGenRdRegister (
1833 GenericRegisterDescriptor
->AddressSpaceId
,
1834 GenericRegisterDescriptor
->RegisterBitWidth
,
1835 GenericRegisterDescriptor
->RegisterBitOffset
,
1836 GenericRegisterDescriptor
->Address
,
1837 GenericRegisterDescriptor
->AccessSize
,
1841 if (EFI_ERROR (Status
)) {
1847 Status
= AmlAppendRdNode (ResourceTemplateNode
, RdNode
);
1848 if (EFI_ERROR (Status
)) {
1854 Status
= AmlVarListAddTail (
1855 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1856 (AML_NODE_HANDLE
)ResourceTemplateNode
1858 if (EFI_ERROR (Status
)) {
1862 ResourceTemplateNode
= NULL
;
1864 // Entry Method: As an integer
1865 Status
= AmlCodeGenInteger (Integer
, &IntegerNode
);
1866 if (EFI_ERROR (Status
)) {
1871 Status
= AmlVarListAddTail (
1872 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1873 (AML_NODE_HANDLE
)IntegerNode
1875 if (EFI_ERROR (Status
)) {
1882 // Residency Counter Register.
1883 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
1884 if (EFI_ERROR (Status
)) {
1886 ResourceTemplateNode
= NULL
;
1889 if (ResidencyCounterRegister
!= NULL
) {
1890 Status
= AmlCodeGenRdRegister (
1891 ResidencyCounterRegister
->AddressSpaceId
,
1892 ResidencyCounterRegister
->RegisterBitWidth
,
1893 ResidencyCounterRegister
->RegisterBitOffset
,
1894 ResidencyCounterRegister
->Address
,
1895 ResidencyCounterRegister
->AccessSize
,
1900 Status
= AmlCodeGenRdRegister (
1901 EFI_ACPI_6_4_SYSTEM_MEMORY
,
1910 if (EFI_ERROR (Status
)) {
1916 Status
= AmlAppendRdNode (ResourceTemplateNode
, RdNode
);
1917 if (EFI_ERROR (Status
)) {
1923 Status
= AmlVarListAddTail (
1924 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1925 (AML_NODE_HANDLE
)ResourceTemplateNode
1927 if (EFI_ERROR (Status
)) {
1931 ResourceTemplateNode
= NULL
;
1933 // Usage Counter Register.
1934 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
1935 if (EFI_ERROR (Status
)) {
1937 ResourceTemplateNode
= NULL
;
1940 if (UsageCounterRegister
!= NULL
) {
1941 Status
= AmlCodeGenRdRegister (
1942 UsageCounterRegister
->AddressSpaceId
,
1943 UsageCounterRegister
->RegisterBitWidth
,
1944 UsageCounterRegister
->RegisterBitOffset
,
1945 UsageCounterRegister
->Address
,
1946 UsageCounterRegister
->AccessSize
,
1951 Status
= AmlCodeGenRdRegister (
1952 EFI_ACPI_6_4_SYSTEM_MEMORY
,
1961 if (EFI_ERROR (Status
)) {
1967 Status
= AmlAppendRdNode (ResourceTemplateNode
, RdNode
);
1968 if (EFI_ERROR (Status
)) {
1974 Status
= AmlVarListAddTail (
1975 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1976 (AML_NODE_HANDLE
)ResourceTemplateNode
1978 if (EFI_ERROR (Status
)) {
1982 ResourceTemplateNode
= NULL
;
1985 if (UsageCounterRegister
!= NULL
) {
1986 Status
= AmlCodeGenString (StateName
, &StringNode
);
1988 Status
= AmlCodeGenString ("", &StringNode
);
1990 if (EFI_ERROR (Status
)) {
1995 Status
= AmlVarListAddTail (
1996 (AML_NODE_HANDLE
)NewLpiPackageNode
,
1997 (AML_NODE_HANDLE
)StringNode
1999 if (EFI_ERROR (Status
)) {
2005 // Add the new LPI state to the LpiNode.
2006 Status
= AmlVarListAddTail (
2007 (AML_NODE_HANDLE
)PackageNode
,
2008 (AML_NODE_HANDLE
)NewLpiPackageNode
2010 if (EFI_ERROR (Status
)) {
2018 if (RdNode
!= NULL
) {
2019 AmlDeleteTree ((AML_NODE_HANDLE
)RdNode
);
2021 if (NewLpiPackageNode
!= NULL
) {
2022 AmlDeleteTree ((AML_NODE_HANDLE
)NewLpiPackageNode
);
2024 if (StringNode
!= NULL
) {
2025 AmlDeleteTree ((AML_NODE_HANDLE
)StringNode
);
2027 if (IntegerNode
!= NULL
) {
2028 AmlDeleteTree ((AML_NODE_HANDLE
)IntegerNode
);
2030 if (ResourceTemplateNode
!= NULL
) {
2031 AmlDeleteTree ((AML_NODE_HANDLE
)ResourceTemplateNode
);