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 <CodeGen/AmlResourceDataCodeGen.h>
16 #include <Tree/AmlNode.h>
17 #include <Tree/AmlTree.h>
18 #include <String/AmlString.h>
19 #include <Utils/AmlUtility.h>
21 /** Utility function to link a node when returning from a CodeGen function.
23 @param [in] Node Newly created node.
24 @param [in] ParentNode If provided, set ParentNode as the parent
26 @param [out] NewObjectNode If not NULL:
27 - and Success, contains the created Node.
28 - and Error, reset to NULL.
30 @retval EFI_SUCCESS The function completed successfully.
31 @retval EFI_INVALID_PARAMETER Invalid parameter.
37 IN AML_OBJECT_NODE
* Node
,
38 IN AML_NODE_HEADER
* ParentNode
,
39 OUT AML_OBJECT_NODE
** NewObjectNode
44 if (NewObjectNode
!= NULL
) {
45 *NewObjectNode
= NULL
;
48 // Add RdNode as the last element.
49 if (ParentNode
!= NULL
) {
50 Status
= AmlVarListAddTail (ParentNode
, (AML_NODE_HEADER
*)Node
);
51 if (EFI_ERROR (Status
)) {
57 if (NewObjectNode
!= NULL
) {
58 *NewObjectNode
= Node
;
64 /** AML code generation for DefinitionBlock.
66 Create a Root Node handle.
67 It is the caller's responsibility to free the allocated memory
68 with the AmlDeleteTree function.
70 AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
71 equivalent to the following ASL code:
72 DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
73 OemID, TableID, OEMRevision) {}
74 with the ComplianceRevision set to 2 and the AMLFileName is ignored.
76 @param[in] TableSignature 4-character ACPI signature.
77 Must be 'DSDT' or 'SSDT'.
78 @param[in] OemId 6-character string OEM identifier.
79 @param[in] OemTableId 8-character string OEM table identifier.
80 @param[in] OemRevision OEM revision number.
81 @param[out] NewRootNode Pointer to the root node representing a
84 @retval EFI_SUCCESS Success.
85 @retval EFI_INVALID_PARAMETER Invalid parameter.
86 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
90 AmlCodeGenDefinitionBlock (
91 IN CONST CHAR8
* TableSignature
,
92 IN CONST CHAR8
* OemId
,
93 IN CONST CHAR8
* OemTableId
,
94 IN UINT32 OemRevision
,
95 OUT AML_ROOT_NODE
** NewRootNode
99 EFI_ACPI_DESCRIPTION_HEADER AcpiHeader
;
101 if ((TableSignature
== NULL
) ||
103 (OemTableId
== NULL
) ||
104 (NewRootNode
== NULL
)) {
106 return EFI_INVALID_PARAMETER
;
109 CopyMem (&AcpiHeader
.Signature
, TableSignature
, 4);
110 AcpiHeader
.Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
111 AcpiHeader
.Revision
= 2;
112 CopyMem (&AcpiHeader
.OemId
, OemId
, 6);
113 CopyMem (&AcpiHeader
.OemTableId
, OemTableId
, 8);
114 AcpiHeader
.OemRevision
= OemRevision
;
115 AcpiHeader
.CreatorId
= TABLE_GENERATOR_CREATOR_ID_ARM
;
116 AcpiHeader
.CreatorRevision
= CREATE_REVISION (1, 0);
118 Status
= AmlCreateRootNode (&AcpiHeader
, NewRootNode
);
119 ASSERT_EFI_ERROR (Status
);
124 /** AML code generation for a String object node.
126 @param [in] String Pointer to a NULL terminated string.
127 @param [out] NewObjectNode If success, contains the created
130 @retval EFI_SUCCESS Success.
131 @retval EFI_INVALID_PARAMETER Invalid parameter.
132 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
139 OUT AML_OBJECT_NODE
** NewObjectNode
143 AML_OBJECT_NODE
* ObjectNode
;
144 AML_DATA_NODE
* DataNode
;
146 if ((String
== NULL
) ||
147 (NewObjectNode
== NULL
)) {
149 return EFI_INVALID_PARAMETER
;
154 Status
= AmlCreateObjectNode (
155 AmlGetByteEncodingByOpCode (AML_STRING_PREFIX
, 0),
159 if (EFI_ERROR (Status
)) {
164 Status
= AmlCreateDataNode (
165 EAmlNodeDataTypeString
,
167 (UINT32
)AsciiStrLen (String
) + 1,
170 if (EFI_ERROR (Status
)) {
175 Status
= AmlSetFixedArgument (
178 (AML_NODE_HEADER
*)DataNode
180 if (EFI_ERROR (Status
)) {
182 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
186 *NewObjectNode
= ObjectNode
;
190 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
194 /** AML code generation for an Integer object node.
196 @param [in] Integer Integer of the Integer object node.
197 @param [out] NewObjectNode If success, contains the created
200 @retval EFI_SUCCESS Success.
201 @retval EFI_INVALID_PARAMETER Invalid parameter.
202 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
209 OUT AML_OBJECT_NODE
** NewObjectNode
215 if (NewObjectNode
== NULL
) {
217 return EFI_INVALID_PARAMETER
;
220 // Create an object node containing Zero.
221 Status
= AmlCreateObjectNode (
222 AmlGetByteEncodingByOpCode (AML_ZERO_OP
, 0),
226 if (EFI_ERROR (Status
)) {
231 // Update the object node with integer value.
232 Status
= AmlNodeSetIntegerValue (*NewObjectNode
, Integer
, &ValueWidthDiff
);
233 if (EFI_ERROR (Status
)) {
235 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
241 /** AML code generation for a Package object node.
243 The package generated is empty. New elements can be added via its
244 list of variable arguments.
246 @param [out] NewObjectNode If success, contains the created
249 @retval EFI_SUCCESS Success.
250 @retval EFI_INVALID_PARAMETER Invalid parameter.
251 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
257 OUT AML_OBJECT_NODE
** NewObjectNode
261 AML_DATA_NODE
* DataNode
;
264 if (NewObjectNode
== NULL
) {
266 return EFI_INVALID_PARAMETER
;
271 // Create an object node.
273 // - one byte to store the PkgLength
274 // - one byte for the NumElements.
275 // Cf ACPI6.3, s20.2.5 "Term Objects Encoding"
276 // DefPackage := PackageOp PkgLength NumElements PackageElementList
277 // NumElements := ByteData
278 Status
= AmlCreateObjectNode (
279 AmlGetByteEncodingByOpCode (AML_PACKAGE_OP
, 0),
283 if (EFI_ERROR (Status
)) {
288 // NumElements is a ByteData.
289 Status
= AmlCreateDataNode (
290 EAmlNodeDataTypeUInt
,
295 if (EFI_ERROR (Status
)) {
300 Status
= AmlSetFixedArgument (
303 (AML_NODE_HEADER
*)DataNode
305 if (EFI_ERROR (Status
)) {
313 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
314 if (DataNode
!= NULL
) {
315 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
320 /** AML code generation for a Buffer object node.
322 To create a Buffer object node with an empty buffer,
323 call the function with (Buffer=NULL, BufferSize=0).
325 @param [in] Buffer Buffer to set for the created Buffer
326 object node. The Buffer's content is copied.
327 NULL if there is no buffer to set for
329 @param [in] BufferSize Size of the Buffer.
330 0 if there is no buffer to set for
332 @param [out] NewObjectNode If success, contains the created
335 @retval EFI_SUCCESS Success.
336 @retval EFI_INVALID_PARAMETER Invalid parameter.
337 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
343 IN CONST UINT8
* Buffer
, OPTIONAL
344 IN UINT32 BufferSize
, OPTIONAL
345 OUT AML_OBJECT_NODE
** NewObjectNode
349 AML_OBJECT_NODE
* BufferNode
;
350 AML_OBJECT_NODE
* BufferSizeNode
;
351 UINT32 BufferSizeNodeSize
;
352 AML_DATA_NODE
* DataNode
;
355 // Buffer and BufferSize must be either both set, or both clear.
356 if ((NewObjectNode
== NULL
) ||
357 ((Buffer
== NULL
) != (BufferSize
== 0))) {
359 return EFI_INVALID_PARAMETER
;
365 // Cf ACPI 6.3 specification, s20.2.5.4 "Type 2 Opcodes Encoding"
366 // DefBuffer := BufferOp PkgLength BufferSize ByteList
368 // BufferSize := TermArg => Integer
370 Status
= AmlCodeGenInteger (BufferSize
, &BufferSizeNode
);
371 if (EFI_ERROR (Status
)) {
376 // Get the number of bytes required to encode the BufferSizeNode.
377 Status
= AmlComputeSize (
378 (AML_NODE_HEADER
*)BufferSizeNode
,
381 if (EFI_ERROR (Status
)) {
386 // Compute the size to write in the PkgLen.
387 Status
= AmlComputePkgLength (BufferSizeNodeSize
+ BufferSize
, &PkgLen
);
388 if (EFI_ERROR (Status
)) {
393 // Create an object node for the buffer.
394 Status
= AmlCreateObjectNode (
395 AmlGetByteEncodingByOpCode (AML_BUFFER_OP
, 0),
399 if (EFI_ERROR (Status
)) {
404 // Set the BufferSizeNode as a fixed argument of the BufferNode.
405 Status
= AmlSetFixedArgument (
408 (AML_NODE_HEADER
*)BufferSizeNode
410 if (EFI_ERROR (Status
)) {
415 // BufferSizeNode is now attached.
416 BufferSizeNode
= NULL
;
418 // If there is a buffer, create a DataNode and attach it to the BufferNode.
419 if (Buffer
!= NULL
) {
420 Status
= AmlCreateDataNode (
426 if (EFI_ERROR (Status
)) {
431 Status
= AmlVarListAddTail (
432 (AML_NODE_HEADER
*)BufferNode
,
433 (AML_NODE_HEADER
*)DataNode
435 if (EFI_ERROR (Status
)) {
441 *NewObjectNode
= BufferNode
;
445 if (BufferSizeNode
!= NULL
) {
446 AmlDeleteTree ((AML_NODE_HEADER
*)BufferSizeNode
);
448 if (BufferNode
!= NULL
) {
449 AmlDeleteTree ((AML_NODE_HEADER
*)BufferNode
);
451 if (DataNode
!= NULL
) {
452 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
457 /** AML code generation for a ResourceTemplate.
459 "ResourceTemplate" is a macro defined in ACPI 6.3, s19.3.3
460 "ASL Resource Templates". It allows to store resource data elements.
462 In AML, a ResourceTemplate is implemented as a Buffer storing resource
463 data elements. An EndTag resource data descriptor must be at the end
464 of the list of resource data elements.
465 This function generates a Buffer node with an EndTag resource data
466 descriptor. It can be seen as an empty list of resource data elements.
468 @param [out] NewObjectNode If success, contains the created
469 ResourceTemplate object node.
471 @retval EFI_SUCCESS Success.
472 @retval EFI_INVALID_PARAMETER Invalid parameter.
473 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
478 AmlCodeGenResourceTemplate (
479 OUT AML_OBJECT_NODE
** NewObjectNode
483 AML_OBJECT_NODE
* BufferNode
;
485 if (NewObjectNode
== NULL
) {
487 return EFI_INVALID_PARAMETER
;
490 // Create a BufferNode with an empty buffer.
491 Status
= AmlCodeGenBuffer (NULL
, 0, &BufferNode
);
492 if (EFI_ERROR (Status
)) {
497 // Create an EndTag resource data element and attach it to the Buffer.
498 Status
= AmlCodeGenEndTag (0, BufferNode
, NULL
);
499 if (EFI_ERROR (Status
)) {
501 AmlDeleteTree ((AML_NODE_HEADER
*)BufferNode
);
505 *NewObjectNode
= BufferNode
;
509 /** AML code generation for a Name object node.
511 @param [in] NameString The new variable name.
512 Must be a NULL-terminated ASL NameString
513 e.g.: "DEV0", "DV15.DEV0", etc.
514 This input string is copied.
515 @param [in] Object Object associated to the NameString.
516 @param [in] ParentNode If provided, set ParentNode as the parent
518 @param [out] NewObjectNode If success, contains the created node.
520 @retval EFI_SUCCESS Success.
521 @retval EFI_INVALID_PARAMETER Invalid parameter.
522 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
528 IN CONST CHAR8
* NameString
,
529 IN AML_OBJECT_NODE
* Object
,
530 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
531 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
535 AML_OBJECT_NODE
* ObjectNode
;
536 AML_DATA_NODE
* DataNode
;
537 CHAR8
* AmlNameString
;
538 UINT32 AmlNameStringSize
;
540 if ((NameString
== NULL
) ||
542 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
544 return EFI_INVALID_PARAMETER
;
549 AmlNameString
= NULL
;
551 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
552 if (EFI_ERROR (Status
)) {
557 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
558 if (EFI_ERROR (Status
)) {
563 Status
= AmlCreateObjectNode (
564 AmlGetByteEncodingByOpCode (AML_NAME_OP
, 0),
568 if (EFI_ERROR (Status
)) {
573 Status
= AmlCreateDataNode (
574 EAmlNodeDataTypeNameString
,
575 (UINT8
*)AmlNameString
,
579 if (EFI_ERROR (Status
)) {
584 Status
= AmlSetFixedArgument (
587 (AML_NODE_HEADER
*)DataNode
589 if (EFI_ERROR (Status
)) {
591 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
595 Status
= AmlSetFixedArgument (
598 (AML_NODE_HEADER
*)Object
600 if (EFI_ERROR (Status
)) {
610 if (EFI_ERROR (Status
)) {
615 // Free AmlNameString before returning as it is copied
616 // in the call to AmlCreateDataNode().
620 if (ObjectNode
!= NULL
) {
621 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
625 if (AmlNameString
!= NULL
) {
626 FreePool (AmlNameString
);
632 /** AML code generation for a Name object node, containing a String.
634 AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
635 equivalent of the following ASL code:
636 Name(_HID, "HID0000")
638 @param [in] NameString The new variable name.
639 Must be a NULL-terminated ASL NameString
640 e.g.: "DEV0", "DV15.DEV0", etc.
641 The input string is copied.
642 @param [in] String NULL terminated String to associate to the
644 @param [in] ParentNode If provided, set ParentNode as the parent
646 @param [out] NewObjectNode If success, contains the created node.
648 @retval EFI_SUCCESS Success.
649 @retval EFI_INVALID_PARAMETER Invalid parameter.
650 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
654 AmlCodeGenNameString (
655 IN CONST CHAR8
* NameString
,
657 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
658 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
662 AML_OBJECT_NODE
* ObjectNode
;
664 if ((NameString
== NULL
) ||
666 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
668 return EFI_INVALID_PARAMETER
;
671 Status
= AmlCodeGenString (String
, &ObjectNode
);
672 if (EFI_ERROR (Status
)) {
677 Status
= AmlCodeGenName (
683 if (EFI_ERROR (Status
)) {
685 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
691 /** AML code generation for a Name object node, containing an Integer.
693 AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
694 equivalent of the following ASL code:
697 @param [in] NameString The new variable name.
698 Must be a NULL-terminated ASL NameString
699 e.g.: "DEV0", "DV15.DEV0", etc.
700 The input string is copied.
701 @param [in] Integer Integer to associate to the NameString.
702 @param [in] ParentNode If provided, set ParentNode as the parent
704 @param [out] NewObjectNode If success, contains the created node.
706 @retval EFI_SUCCESS Success.
707 @retval EFI_INVALID_PARAMETER Invalid parameter.
708 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
712 AmlCodeGenNameInteger (
713 IN CONST CHAR8
* NameString
,
715 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
716 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
720 AML_OBJECT_NODE
* ObjectNode
;
722 if ((NameString
== NULL
) ||
723 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
725 return EFI_INVALID_PARAMETER
;
728 Status
= AmlCodeGenInteger (Integer
, &ObjectNode
);
729 if (EFI_ERROR (Status
)) {
734 Status
= AmlCodeGenName (
740 if (EFI_ERROR (Status
)) {
742 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
748 /** AML code generation for a Device object node.
750 AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
751 equivalent of the following ASL code:
754 @param [in] NameString The new Device's name.
755 Must be a NULL-terminated ASL NameString
756 e.g.: "DEV0", "DV15.DEV0", etc.
757 The input string is copied.
758 @param [in] ParentNode If provided, set ParentNode as the parent
760 @param [out] NewObjectNode If success, contains the created node.
762 @retval EFI_SUCCESS Success.
763 @retval EFI_INVALID_PARAMETER Invalid parameter.
764 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
769 IN CONST CHAR8
* NameString
,
770 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
771 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
775 AML_OBJECT_NODE
* ObjectNode
;
776 AML_DATA_NODE
* DataNode
;
777 CHAR8
* AmlNameString
;
778 UINT32 AmlNameStringSize
;
780 if ((NameString
== NULL
) ||
781 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
783 return EFI_INVALID_PARAMETER
;
788 AmlNameString
= NULL
;
790 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
791 if (EFI_ERROR (Status
)) {
796 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
797 if (EFI_ERROR (Status
)) {
802 Status
= AmlCreateObjectNode (
803 AmlGetByteEncodingByOpCode (AML_EXT_OP
, AML_EXT_DEVICE_OP
),
804 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
807 if (EFI_ERROR (Status
)) {
812 Status
= AmlCreateDataNode (
813 EAmlNodeDataTypeNameString
,
814 (UINT8
*)AmlNameString
,
818 if (EFI_ERROR (Status
)) {
823 Status
= AmlSetFixedArgument (
826 (AML_NODE_HEADER
*)DataNode
828 if (EFI_ERROR (Status
)) {
830 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
839 if (EFI_ERROR (Status
)) {
844 // Free AmlNameString before returning as it is copied
845 // in the call to AmlCreateDataNode().
849 if (ObjectNode
!= NULL
) {
850 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
854 if (AmlNameString
!= NULL
) {
855 FreePool (AmlNameString
);
861 /** AML code generation for a Scope object node.
863 AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
864 equivalent of the following ASL code:
867 @param [in] NameString The new Scope's name.
868 Must be a NULL-terminated ASL NameString
869 e.g.: "DEV0", "DV15.DEV0", etc.
870 The input string is copied.
871 @param [in] ParentNode If provided, set ParentNode as the parent
873 @param [out] NewObjectNode If success, contains the created node.
875 @retval EFI_SUCCESS Success.
876 @retval EFI_INVALID_PARAMETER Invalid parameter.
877 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
882 IN CONST CHAR8
* NameString
,
883 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
884 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
888 AML_OBJECT_NODE
* ObjectNode
;
889 AML_DATA_NODE
* DataNode
;
890 CHAR8
* AmlNameString
;
891 UINT32 AmlNameStringSize
;
893 if ((NameString
== NULL
) ||
894 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
896 return EFI_INVALID_PARAMETER
;
901 AmlNameString
= NULL
;
903 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
904 if (EFI_ERROR (Status
)) {
909 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
910 if (EFI_ERROR (Status
)) {
915 Status
= AmlCreateObjectNode (
916 AmlGetByteEncodingByOpCode (AML_SCOPE_OP
, 0),
917 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
920 if (EFI_ERROR (Status
)) {
925 Status
= AmlCreateDataNode (
926 EAmlNodeDataTypeNameString
,
927 (UINT8
*)AmlNameString
,
931 if (EFI_ERROR (Status
)) {
936 Status
= AmlSetFixedArgument (
939 (AML_NODE_HEADER
*)DataNode
941 if (EFI_ERROR (Status
)) {
943 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
952 if (EFI_ERROR (Status
)) {
957 // Free AmlNameString before returning as it is copied
958 // in the call to AmlCreateDataNode().
962 if (ObjectNode
!= NULL
) {
963 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
967 if (AmlNameString
!= NULL
) {
968 FreePool (AmlNameString
);
974 /** AML code generation for a Method object node.
976 AmlCodeGenMethod ("MET0", 1, TRUE, 3, ParentNode, NewObjectNode) is
977 equivalent of the following ASL code:
978 Method(MET0, 1, Serialized, 3) {}
980 ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
981 DefMethod := MethodOp PkgLength NameString MethodFlags TermList
984 The ASL parameters "ReturnType" and "ParameterTypes" are not asked
985 in this function. They are optional parameters in ASL.
987 @param [in] NameString The new Method's name.
988 Must be a NULL-terminated ASL NameString
989 e.g.: "MET0", "_SB.MET0", etc.
990 The input string is copied.
991 @param [in] NumArgs Number of arguments.
992 Must be 0 <= NumArgs <= 6.
993 @param [in] IsSerialized TRUE is equivalent to Serialized.
994 FALSE is equivalent to NotSerialized.
995 Default is NotSerialized in ASL spec.
996 @param [in] SyncLevel Synchronization level for the method.
997 Must be 0 <= SyncLevel <= 15.
999 @param [in] ParentNode If provided, set ParentNode as the parent
1000 of the node created.
1001 @param [out] NewObjectNode If success, contains the created node.
1003 @retval EFI_SUCCESS Success.
1004 @retval EFI_INVALID_PARAMETER Invalid parameter.
1005 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1011 IN CONST CHAR8
* NameString
,
1013 IN BOOLEAN IsSerialized
,
1015 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
1016 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
1022 AML_OBJECT_NODE
* ObjectNode
;
1023 AML_DATA_NODE
* DataNode
;
1024 CHAR8
* AmlNameString
;
1025 UINT32 AmlNameStringSize
;
1027 if ((NameString
== NULL
) ||
1030 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
1032 return EFI_INVALID_PARAMETER
;
1038 // ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
1039 // DefMethod := MethodOp PkgLength NameString MethodFlags TermList
1042 // 1- Create the NameString
1043 // 2- Compute the size to write in the PkgLen
1044 // 3- Create nodes for the NameString and Method object node
1045 // 4- Set the NameString DataNode as a fixed argument
1046 // 5- Create and link the MethodFlags node
1048 // 1- Create the NameString
1049 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1050 if (EFI_ERROR (Status
)) {
1055 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1056 if (EFI_ERROR (Status
)) {
1058 goto error_handler1
;
1061 // 2- Compute the size to write in the PkgLen
1062 // Add 1 byte (ByteData) for MethodFlags.
1063 Status
= AmlComputePkgLength (AmlNameStringSize
+ 1, &PkgLen
);
1064 if (EFI_ERROR (Status
)) {
1066 goto error_handler1
;
1069 // 3- Create nodes for the NameString and Method object node
1070 Status
= AmlCreateObjectNode (
1071 AmlGetByteEncodingByOpCode (AML_METHOD_OP
, 0),
1075 if (EFI_ERROR (Status
)) {
1077 goto error_handler1
;
1080 Status
= AmlCreateDataNode (
1081 EAmlNodeDataTypeNameString
,
1082 (UINT8
*)AmlNameString
,
1086 if (EFI_ERROR (Status
)) {
1088 goto error_handler2
;
1091 // 4- Set the NameString DataNode as a fixed argument
1092 Status
= AmlSetFixedArgument (
1094 EAmlParseIndexTerm0
,
1095 (AML_NODE_HEADER
*)DataNode
1097 if (EFI_ERROR (Status
)) {
1099 goto error_handler2
;
1104 // 5- Create and link the MethodFlags node
1106 (IsSerialized
? BIT3
: 0) |
1109 Status
= AmlCreateDataNode (EAmlNodeDataTypeUInt
, &Flags
, 1, &DataNode
);
1110 if (EFI_ERROR (Status
)) {
1112 goto error_handler2
;
1115 Status
= AmlSetFixedArgument (
1117 EAmlParseIndexTerm1
,
1118 (AML_NODE_HEADER
*)DataNode
1120 if (EFI_ERROR (Status
)) {
1122 goto error_handler2
;
1125 // Data node is attached so set the pointer to
1126 // NULL to ensure correct error handling.
1134 if (EFI_ERROR (Status
)) {
1136 goto error_handler2
;
1139 // Free AmlNameString before returning as it is copied
1140 // in the call to AmlCreateDataNode().
1141 goto error_handler1
;
1144 if (ObjectNode
!= NULL
) {
1145 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1147 if (DataNode
!= NULL
) {
1148 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
1152 if (AmlNameString
!= NULL
) {
1153 FreePool (AmlNameString
);
1158 /** AML code generation for a Return object node.
1160 AmlCodeGenReturn (ReturnNode, ParentNode, NewObjectNode) is
1161 equivalent of the following ASL code:
1162 Return([Content of the ReturnNode])
1164 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:
1165 DefReturn := ReturnOp ArgObject
1167 ArgObject := TermArg => DataRefObject
1169 Thus, the ReturnNode must be evaluated as a DataRefObject. It can
1170 be a NameString referencing an object. As this CodeGen Api doesn't
1171 do semantic checking, it is strongly advised to check the AML bytecode
1172 generated by this function against an ASL compiler.
1174 The ReturnNode must be generated inside a Method body scope.
1176 @param [in] ReturnNode The object returned by the Return ASL statement.
1177 This node is deleted if an error occurs.
1178 @param [in] ParentNode If provided, set ParentNode as the parent
1179 of the node created.
1180 Must be a MethodOp node.
1181 @param [out] NewObjectNode If success, contains the created node.
1183 @retval EFI_SUCCESS Success.
1184 @retval EFI_INVALID_PARAMETER Invalid parameter.
1185 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1191 IN AML_NODE_HEADER
* ReturnNode
,
1192 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
1193 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
1197 AML_OBJECT_NODE
* ObjectNode
;
1199 if ((ReturnNode
== NULL
) ||
1200 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)) ||
1201 ((ParentNode
!= NULL
) &&
1202 !AmlNodeCompareOpCode (
1203 (AML_OBJECT_NODE
*)ParentNode
, AML_METHOD_OP
, 0))) {
1205 return EFI_INVALID_PARAMETER
;
1208 Status
= AmlCreateObjectNode (
1209 AmlGetByteEncodingByOpCode (AML_RETURN_OP
, 0),
1213 if (EFI_ERROR (Status
)) {
1218 Status
= AmlSetFixedArgument (
1220 EAmlParseIndexTerm0
,
1221 (AML_NODE_HEADER
*)ReturnNode
1223 if (EFI_ERROR (Status
)) {
1235 if (EFI_ERROR (Status
)) {
1243 if (ReturnNode
!= NULL
) {
1244 AmlDeleteTree (ReturnNode
);
1246 if (ObjectNode
!= NULL
) {
1247 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1252 /** AML code generation for a Return object node,
1253 returning the object as an input NameString.
1255 AmlCodeGenReturn ("NAM1", ParentNode, NewObjectNode) is
1256 equivalent of the following ASL code:
1259 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:
1260 DefReturn := ReturnOp ArgObject
1262 ArgObject := TermArg => DataRefObject
1264 Thus, the ReturnNode must be evaluated as a DataRefObject. It can
1265 be a NameString referencing an object. As this CodeGen Api doesn't
1266 do semantic checking, it is strongly advised to check the AML bytecode
1267 generated by this function against an ASL compiler.
1269 The ReturnNode must be generated inside a Method body scope.
1271 @param [in] NameString The object referenced by this NameString
1272 is returned by the Return ASL statement.
1273 Must be a NULL-terminated ASL NameString
1274 e.g.: "NAM1", "_SB.NAM1", etc.
1275 The input string is copied.
1276 @param [in] ParentNode If provided, set ParentNode as the parent
1277 of the node created.
1278 Must be a MethodOp node.
1279 @param [out] NewObjectNode If success, contains the created node.
1281 @retval EFI_SUCCESS Success.
1282 @retval EFI_INVALID_PARAMETER Invalid parameter.
1283 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1288 AmlCodeGenReturnNameString (
1289 IN CONST CHAR8
* NameString
,
1290 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
1291 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
1295 AML_DATA_NODE
* DataNode
;
1296 CHAR8
* AmlNameString
;
1297 UINT32 AmlNameStringSize
;
1301 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1302 if (EFI_ERROR (Status
)) {
1307 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1308 if (EFI_ERROR (Status
)) {
1313 Status
= AmlCreateDataNode (
1314 EAmlNodeDataTypeNameString
,
1315 (UINT8
*)AmlNameString
,
1319 if (EFI_ERROR (Status
)) {
1324 // AmlCodeGenReturn() deletes DataNode if error.
1325 Status
= AmlCodeGenReturn (
1326 (AML_NODE_HEADER
*)DataNode
,
1330 ASSERT_EFI_ERROR (Status
);
1333 if (AmlNameString
!= NULL
) {
1334 FreePool (AmlNameString
);