4 Copyright (c) 2020 - 2022, 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 <AmlCpcInfo.h>
15 #include <AmlEncoding/Aml.h>
16 #include <Api/AmlApiHelper.h>
17 #include <CodeGen/AmlResourceDataCodeGen.h>
18 #include <Tree/AmlNode.h>
19 #include <Tree/AmlTree.h>
20 #include <String/AmlString.h>
21 #include <Utils/AmlUtility.h>
23 /** Utility function to link a node when returning from a CodeGen function.
25 @param [in] Node Newly created node.
26 @param [in] ParentNode If provided, set ParentNode as the parent
28 @param [out] NewObjectNode If not NULL:
29 - and Success, contains the created Node.
30 - and Error, reset to NULL.
32 @retval EFI_SUCCESS The function completed successfully.
33 @retval EFI_INVALID_PARAMETER Invalid parameter.
39 IN AML_OBJECT_NODE
*Node
,
40 IN AML_NODE_HEADER
*ParentNode
,
41 OUT AML_OBJECT_NODE
**NewObjectNode
46 if (NewObjectNode
!= NULL
) {
47 *NewObjectNode
= NULL
;
50 // Add RdNode as the last element.
51 if (ParentNode
!= NULL
) {
52 Status
= AmlVarListAddTail (ParentNode
, (AML_NODE_HEADER
*)Node
);
53 if (EFI_ERROR (Status
)) {
59 if (NewObjectNode
!= NULL
) {
60 *NewObjectNode
= Node
;
66 /** AML code generation for DefinitionBlock.
68 Create a Root Node handle.
69 It is the caller's responsibility to free the allocated memory
70 with the AmlDeleteTree function.
72 AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
73 equivalent to the following ASL code:
74 DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
75 OemID, TableID, OEMRevision) {}
76 with the ComplianceRevision set to 2 and the AMLFileName is ignored.
78 @param[in] TableSignature 4-character ACPI signature.
79 Must be 'DSDT' or 'SSDT'.
80 @param[in] OemId 6-character string OEM identifier.
81 @param[in] OemTableId 8-character string OEM table identifier.
82 @param[in] OemRevision OEM revision number.
83 @param[out] NewRootNode Pointer to the root node representing a
86 @retval EFI_SUCCESS Success.
87 @retval EFI_INVALID_PARAMETER Invalid parameter.
88 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
92 AmlCodeGenDefinitionBlock (
93 IN CONST CHAR8
*TableSignature
,
94 IN CONST CHAR8
*OemId
,
95 IN CONST CHAR8
*OemTableId
,
96 IN UINT32 OemRevision
,
97 OUT AML_ROOT_NODE
**NewRootNode
101 EFI_ACPI_DESCRIPTION_HEADER AcpiHeader
;
103 if ((TableSignature
== NULL
) ||
105 (OemTableId
== NULL
) ||
106 (NewRootNode
== NULL
))
109 return EFI_INVALID_PARAMETER
;
112 CopyMem (&AcpiHeader
.Signature
, TableSignature
, 4);
113 AcpiHeader
.Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
114 AcpiHeader
.Revision
= 2;
115 CopyMem (&AcpiHeader
.OemId
, OemId
, 6);
116 CopyMem (&AcpiHeader
.OemTableId
, OemTableId
, 8);
117 AcpiHeader
.OemRevision
= OemRevision
;
118 AcpiHeader
.CreatorId
= TABLE_GENERATOR_CREATOR_ID_ARM
;
119 AcpiHeader
.CreatorRevision
= CREATE_REVISION (1, 0);
121 Status
= AmlCreateRootNode (&AcpiHeader
, NewRootNode
);
122 ASSERT_EFI_ERROR (Status
);
127 /** AML code generation for a String object node.
129 @param [in] String Pointer to a NULL terminated string.
130 @param [out] NewObjectNode If success, contains the created
133 @retval EFI_SUCCESS Success.
134 @retval EFI_INVALID_PARAMETER Invalid parameter.
135 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
142 OUT AML_OBJECT_NODE
**NewObjectNode
146 AML_OBJECT_NODE
*ObjectNode
;
147 AML_DATA_NODE
*DataNode
;
149 if ((String
== NULL
) ||
150 (NewObjectNode
== NULL
))
153 return EFI_INVALID_PARAMETER
;
158 Status
= AmlCreateObjectNode (
159 AmlGetByteEncodingByOpCode (AML_STRING_PREFIX
, 0),
163 if (EFI_ERROR (Status
)) {
168 Status
= AmlCreateDataNode (
169 EAmlNodeDataTypeString
,
171 (UINT32
)AsciiStrLen (String
) + 1,
174 if (EFI_ERROR (Status
)) {
179 Status
= AmlSetFixedArgument (
182 (AML_NODE_HEADER
*)DataNode
184 if (EFI_ERROR (Status
)) {
186 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
190 *NewObjectNode
= ObjectNode
;
194 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
198 /** AML code generation for an Integer object node.
200 @param [in] Integer Integer of the Integer object node.
201 @param [out] NewObjectNode If success, contains the created
204 @retval EFI_SUCCESS Success.
205 @retval EFI_INVALID_PARAMETER Invalid parameter.
206 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
213 OUT AML_OBJECT_NODE
**NewObjectNode
219 if (NewObjectNode
== NULL
) {
221 return EFI_INVALID_PARAMETER
;
224 // Create an object node containing Zero.
225 Status
= AmlCreateObjectNode (
226 AmlGetByteEncodingByOpCode (AML_ZERO_OP
, 0),
230 if (EFI_ERROR (Status
)) {
235 // Update the object node with integer value.
236 Status
= AmlNodeSetIntegerValue (*NewObjectNode
, Integer
, &ValueWidthDiff
);
237 if (EFI_ERROR (Status
)) {
239 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
245 /** AML code generation for a Package object node.
247 The package generated is empty. New elements can be added via its
248 list of variable arguments.
250 @param [out] NewObjectNode If success, contains the created
253 @retval EFI_SUCCESS Success.
254 @retval EFI_INVALID_PARAMETER Invalid parameter.
255 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
261 OUT AML_OBJECT_NODE
**NewObjectNode
265 AML_DATA_NODE
*DataNode
;
268 if (NewObjectNode
== NULL
) {
270 return EFI_INVALID_PARAMETER
;
275 // Create an object node.
277 // - one byte to store the PkgLength
278 // - one byte for the NumElements.
279 // Cf ACPI6.3, s20.2.5 "Term Objects Encoding"
280 // DefPackage := PackageOp PkgLength NumElements PackageElementList
281 // NumElements := ByteData
282 Status
= AmlCreateObjectNode (
283 AmlGetByteEncodingByOpCode (AML_PACKAGE_OP
, 0),
287 if (EFI_ERROR (Status
)) {
292 // NumElements is a ByteData.
293 Status
= AmlCreateDataNode (
294 EAmlNodeDataTypeUInt
,
299 if (EFI_ERROR (Status
)) {
304 Status
= AmlSetFixedArgument (
307 (AML_NODE_HEADER
*)DataNode
309 if (EFI_ERROR (Status
)) {
317 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
318 if (DataNode
!= NULL
) {
319 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
325 /** AML code generation for a Buffer object node.
327 To create a Buffer object node with an empty buffer,
328 call the function with (Buffer=NULL, BufferSize=0).
330 @param [in] Buffer Buffer to set for the created Buffer
331 object node. The Buffer's content is copied.
332 NULL if there is no buffer to set for
334 @param [in] BufferSize Size of the Buffer.
335 0 if there is no buffer to set for
337 @param [out] NewObjectNode If success, contains the created
340 @retval EFI_SUCCESS Success.
341 @retval EFI_INVALID_PARAMETER Invalid parameter.
342 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
348 IN CONST UINT8
*Buffer OPTIONAL
,
349 IN UINT32 BufferSize OPTIONAL
,
350 OUT AML_OBJECT_NODE
**NewObjectNode
354 AML_OBJECT_NODE
*BufferNode
;
355 AML_OBJECT_NODE
*BufferSizeNode
;
356 UINT32 BufferSizeNodeSize
;
357 AML_DATA_NODE
*DataNode
;
360 // Buffer and BufferSize must be either both set, or both clear.
361 if ((NewObjectNode
== NULL
) ||
362 ((Buffer
== NULL
) != (BufferSize
== 0)))
365 return EFI_INVALID_PARAMETER
;
371 // Cf ACPI 6.3 specification, s20.2.5.4 "Type 2 Opcodes Encoding"
372 // DefBuffer := BufferOp PkgLength BufferSize ByteList
374 // BufferSize := TermArg => Integer
376 Status
= AmlCodeGenInteger (BufferSize
, &BufferSizeNode
);
377 if (EFI_ERROR (Status
)) {
382 // Get the number of bytes required to encode the BufferSizeNode.
383 Status
= AmlComputeSize (
384 (AML_NODE_HEADER
*)BufferSizeNode
,
387 if (EFI_ERROR (Status
)) {
392 // Compute the size to write in the PkgLen.
393 Status
= AmlComputePkgLength (BufferSizeNodeSize
+ BufferSize
, &PkgLen
);
394 if (EFI_ERROR (Status
)) {
399 // Create an object node for the buffer.
400 Status
= AmlCreateObjectNode (
401 AmlGetByteEncodingByOpCode (AML_BUFFER_OP
, 0),
405 if (EFI_ERROR (Status
)) {
410 // Set the BufferSizeNode as a fixed argument of the BufferNode.
411 Status
= AmlSetFixedArgument (
414 (AML_NODE_HEADER
*)BufferSizeNode
416 if (EFI_ERROR (Status
)) {
421 // BufferSizeNode is now attached.
422 BufferSizeNode
= NULL
;
424 // If there is a buffer, create a DataNode and attach it to the BufferNode.
425 if (Buffer
!= NULL
) {
426 Status
= AmlCreateDataNode (
432 if (EFI_ERROR (Status
)) {
437 Status
= AmlVarListAddTail (
438 (AML_NODE_HEADER
*)BufferNode
,
439 (AML_NODE_HEADER
*)DataNode
441 if (EFI_ERROR (Status
)) {
447 *NewObjectNode
= BufferNode
;
451 if (BufferSizeNode
!= NULL
) {
452 AmlDeleteTree ((AML_NODE_HEADER
*)BufferSizeNode
);
455 if (BufferNode
!= NULL
) {
456 AmlDeleteTree ((AML_NODE_HEADER
*)BufferNode
);
459 if (DataNode
!= NULL
) {
460 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
466 /** AML code generation for a ResourceTemplate.
468 "ResourceTemplate" is a macro defined in ACPI 6.3, s19.3.3
469 "ASL Resource Templates". It allows to store resource data elements.
471 In AML, a ResourceTemplate is implemented as a Buffer storing resource
472 data elements. An EndTag resource data descriptor must be at the end
473 of the list of resource data elements.
474 This function generates a Buffer node with an EndTag resource data
475 descriptor. It can be seen as an empty list of resource data elements.
477 @param [out] NewObjectNode If success, contains the created
478 ResourceTemplate object node.
480 @retval EFI_SUCCESS Success.
481 @retval EFI_INVALID_PARAMETER Invalid parameter.
482 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
487 AmlCodeGenResourceTemplate (
488 OUT AML_OBJECT_NODE
**NewObjectNode
492 AML_OBJECT_NODE
*BufferNode
;
494 if (NewObjectNode
== NULL
) {
496 return EFI_INVALID_PARAMETER
;
499 // Create a BufferNode with an empty buffer.
500 Status
= AmlCodeGenBuffer (NULL
, 0, &BufferNode
);
501 if (EFI_ERROR (Status
)) {
506 // Create an EndTag resource data element and attach it to the Buffer.
507 Status
= AmlCodeGenEndTag (0, BufferNode
, NULL
);
508 if (EFI_ERROR (Status
)) {
510 AmlDeleteTree ((AML_NODE_HEADER
*)BufferNode
);
514 *NewObjectNode
= BufferNode
;
518 /** AML code generation for a Name object node.
520 @param [in] NameString The new variable name.
521 Must be a NULL-terminated ASL NameString
522 e.g.: "DEV0", "DV15.DEV0", etc.
523 This input string is copied.
524 @param [in] Object Object associated to the NameString.
525 @param [in] ParentNode If provided, set ParentNode as the parent
527 @param [out] NewObjectNode If success, contains the created node.
529 @retval EFI_SUCCESS Success.
530 @retval EFI_INVALID_PARAMETER Invalid parameter.
531 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
537 IN CONST CHAR8
*NameString
,
538 IN AML_OBJECT_NODE
*Object
,
539 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
540 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
544 AML_OBJECT_NODE
*ObjectNode
;
545 AML_DATA_NODE
*DataNode
;
546 CHAR8
*AmlNameString
;
547 UINT32 AmlNameStringSize
;
549 if ((NameString
== NULL
) ||
551 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
554 return EFI_INVALID_PARAMETER
;
559 AmlNameString
= NULL
;
561 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
562 if (EFI_ERROR (Status
)) {
567 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
568 if (EFI_ERROR (Status
)) {
573 Status
= AmlCreateObjectNode (
574 AmlGetByteEncodingByOpCode (AML_NAME_OP
, 0),
578 if (EFI_ERROR (Status
)) {
583 Status
= AmlCreateDataNode (
584 EAmlNodeDataTypeNameString
,
585 (UINT8
*)AmlNameString
,
589 if (EFI_ERROR (Status
)) {
594 Status
= AmlSetFixedArgument (
597 (AML_NODE_HEADER
*)DataNode
599 if (EFI_ERROR (Status
)) {
601 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
605 Status
= AmlSetFixedArgument (
608 (AML_NODE_HEADER
*)Object
610 if (EFI_ERROR (Status
)) {
620 if (EFI_ERROR (Status
)) {
625 // Free AmlNameString before returning as it is copied
626 // in the call to AmlCreateDataNode().
630 if (ObjectNode
!= NULL
) {
631 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
635 if (AmlNameString
!= NULL
) {
636 FreePool (AmlNameString
);
642 /** AML code generation for a Name object node, containing a String.
644 AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
645 equivalent of the following ASL code:
646 Name(_HID, "HID0000")
648 @param [in] NameString The new variable name.
649 Must be a NULL-terminated ASL NameString
650 e.g.: "DEV0", "DV15.DEV0", etc.
651 The input string is copied.
652 @param [in] String NULL terminated String to associate to the
654 @param [in] ParentNode If provided, set ParentNode as the parent
656 @param [out] NewObjectNode If success, contains the created node.
658 @retval EFI_SUCCESS Success.
659 @retval EFI_INVALID_PARAMETER Invalid parameter.
660 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
664 AmlCodeGenNameString (
665 IN CONST CHAR8
*NameString
,
667 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
668 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
672 AML_OBJECT_NODE
*ObjectNode
;
674 if ((NameString
== NULL
) ||
676 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
679 return EFI_INVALID_PARAMETER
;
682 Status
= AmlCodeGenString (String
, &ObjectNode
);
683 if (EFI_ERROR (Status
)) {
688 Status
= AmlCodeGenName (
694 if (EFI_ERROR (Status
)) {
696 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
702 /** AML code generation for a Name object node, containing an Integer.
704 AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
705 equivalent of the following ASL code:
708 @param [in] NameString The new variable name.
709 Must be a NULL-terminated ASL NameString
710 e.g.: "DEV0", "DV15.DEV0", etc.
711 The input string is copied.
712 @param [in] Integer Integer to associate to the NameString.
713 @param [in] ParentNode If provided, set ParentNode as the parent
715 @param [out] NewObjectNode If success, contains the created node.
717 @retval EFI_SUCCESS Success.
718 @retval EFI_INVALID_PARAMETER Invalid parameter.
719 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
723 AmlCodeGenNameInteger (
724 IN CONST CHAR8
*NameString
,
726 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
727 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
731 AML_OBJECT_NODE
*ObjectNode
;
733 if ((NameString
== NULL
) ||
734 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
737 return EFI_INVALID_PARAMETER
;
740 Status
= AmlCodeGenInteger (Integer
, &ObjectNode
);
741 if (EFI_ERROR (Status
)) {
746 Status
= AmlCodeGenName (
752 if (EFI_ERROR (Status
)) {
754 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
760 /** AML code generation for a Name object node, containing a Package.
762 AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
763 equivalent of the following ASL code:
764 Name(PKG0, Package () {})
766 @param [in] NameString The new variable name.
767 Must be a NULL-terminated ASL NameString
768 e.g.: "DEV0", "DV15.DEV0", etc.
769 The input string is copied.
770 @param [in] ParentNode If provided, set ParentNode as the parent
772 @param [out] NewObjectNode If success, contains the created node.
774 @retval EFI_SUCCESS Success.
775 @retval EFI_INVALID_PARAMETER Invalid parameter.
776 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
780 AmlCodeGenNamePackage (
781 IN CONST CHAR8
*NameString
,
782 IN AML_NODE_HEADER
*ParentNode
, OPTIONAL
783 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
787 AML_OBJECT_NODE
*PackageNode
;
789 if ((NameString
== NULL
) ||
790 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
793 return EFI_INVALID_PARAMETER
;
796 Status
= AmlCodeGenPackage (&PackageNode
);
797 if (EFI_ERROR (Status
)) {
802 Status
= AmlCodeGenName (
808 if (EFI_ERROR (Status
)) {
810 AmlDeleteTree ((AML_NODE_HEADER
*)PackageNode
);
816 /** AML code generation for a Name object node, containing a ResourceTemplate.
818 AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
819 equivalent of the following ASL code:
820 Name(PRS0, ResourceTemplate () {})
822 @param [in] NameString The new variable name.
823 Must be a NULL-terminated ASL NameString
824 e.g.: "DEV0", "DV15.DEV0", etc.
825 The input string is copied.
826 @param [in] ParentNode If provided, set ParentNode as the parent
828 @param [out] NewObjectNode If success, contains the created node.
830 @retval EFI_SUCCESS Success.
831 @retval EFI_INVALID_PARAMETER Invalid parameter.
832 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
836 AmlCodeGenNameResourceTemplate (
837 IN CONST CHAR8
*NameString
,
838 IN AML_NODE_HEADER
*ParentNode
, OPTIONAL
839 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
843 AML_OBJECT_NODE
*ResourceTemplateNode
;
845 if ((NameString
== NULL
) ||
846 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
849 return EFI_INVALID_PARAMETER
;
852 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
853 if (EFI_ERROR (Status
)) {
858 Status
= AmlCodeGenName (
860 ResourceTemplateNode
,
864 if (EFI_ERROR (Status
)) {
866 AmlDeleteTree ((AML_NODE_HEADER
*)ResourceTemplateNode
);
872 /** Add a _PRT entry.
874 AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
875 equivalent of the following ASL code:
877 0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
878 0, // Pin: PCI pin number of the device (0-INTA, ...).
879 LNKA // Source: Name of the device that allocates the interrupt
880 // to which the above pin is connected.
881 0 // Source Index: Source is assumed to only describe one
882 // interrupt, so let it to index 0.
885 The 2 models described in ACPI 6.4, s6.2.13 "_PRT (PCI Routing Table)" can
886 be generated by this function. The example above matches the first model.
888 The package is added at the tail of the list of the input _PRT node
890 Name (_PRT, Package () {
891 [Pre-existing _PRT entries],
892 [Newly created _PRT entry]
895 Cf. ACPI 6.4 specification:
896 - s6.2.13 "_PRT (PCI Routing Table)"
897 - s6.1.1 "_ADR (Address)"
899 @param [in] Address Address. Cf ACPI 6.4 specification, Table 6.2:
900 "ADR Object Address Encodings":
901 High word-Device #, Low word-Function #. (for
902 example, device 3, function 2 is 0x00030002).
903 To refer to all the functions on a device #,
904 use a function number of FFFF).
905 @param [in] Pin PCI pin number of the device (0-INTA ... 3-INTD).
907 @param [in] LinkName Link Name, i.e. device in the AML NameSpace
908 describing the interrupt used. The input string
910 If NULL, generate 0 in the 'Source' field (cf.
911 second model, using GSIV).
912 @param [in] SourceIndex Source index or GSIV.
913 @param [in] PrtNameNode Prt Named node to add the object to ....
915 @retval EFI_SUCCESS Success.
916 @retval EFI_INVALID_PARAMETER Invalid parameter.
917 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
924 IN CONST CHAR8
*LinkName
,
925 IN UINT32 SourceIndex
,
926 IN AML_OBJECT_NODE_HANDLE PrtNameNode
930 AML_OBJECT_NODE
*PrtEntryList
;
931 AML_OBJECT_NODE
*PackageNode
;
932 AML_OBJECT_NODE
*NewElementNode
;
934 CHAR8
*AmlNameString
;
935 UINT32 AmlNameStringSize
;
936 AML_DATA_NODE
*DataNode
;
939 (PrtNameNode
== NULL
) ||
940 (AmlGetNodeType ((AML_NODE_HANDLE
)PrtNameNode
) != EAmlNodeObject
) ||
941 (!AmlNodeHasOpCode (PrtNameNode
, AML_NAME_OP
, 0)) ||
942 !AmlNameOpCompareName (PrtNameNode
, "_PRT"))
945 return EFI_INVALID_PARAMETER
;
948 NewElementNode
= NULL
;
949 AmlNameString
= NULL
;
952 // Get the Package object node of the _PRT node,
953 // which is the 2nd fixed argument (i.e. index 1).
954 PrtEntryList
= (AML_OBJECT_NODE_HANDLE
)AmlGetFixedArgument (
958 if ((PrtEntryList
== NULL
) ||
959 (AmlGetNodeType ((AML_NODE_HANDLE
)PrtEntryList
) != EAmlNodeObject
) ||
960 (!AmlNodeHasOpCode (PrtEntryList
, AML_PACKAGE_OP
, 0)))
963 return EFI_INVALID_PARAMETER
;
966 // The new _PRT entry.
967 Status
= AmlCodeGenPackage (&PackageNode
);
968 if (EFI_ERROR (Status
)) {
973 Status
= AmlCodeGenInteger (Address
, &NewElementNode
);
974 if (EFI_ERROR (Status
)) {
979 Status
= AmlVarListAddTail (
980 (AML_NODE_HANDLE
)PackageNode
,
981 (AML_NODE_HANDLE
)NewElementNode
983 if (EFI_ERROR (Status
)) {
988 NewElementNode
= NULL
;
990 Status
= AmlCodeGenInteger (Pin
, &NewElementNode
);
991 if (EFI_ERROR (Status
)) {
996 Status
= AmlVarListAddTail (
997 (AML_NODE_HANDLE
)PackageNode
,
998 (AML_NODE_HANDLE
)NewElementNode
1000 if (EFI_ERROR (Status
)) {
1005 NewElementNode
= NULL
;
1007 if (LinkName
!= NULL
) {
1008 Status
= ConvertAslNameToAmlName (LinkName
, &AmlNameString
);
1009 if (EFI_ERROR (Status
)) {
1010 ASSERT_EFI_ERROR (Status
);
1014 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1015 if (EFI_ERROR (Status
)) {
1016 ASSERT_EFI_ERROR (Status
);
1020 Status
= AmlCreateDataNode (
1021 EAmlNodeDataTypeNameString
,
1022 (UINT8
*)AmlNameString
,
1026 if (EFI_ERROR (Status
)) {
1027 ASSERT_EFI_ERROR (Status
);
1031 // AmlNameString will be freed be fore returning.
1033 Status
= AmlVarListAddTail (
1034 (AML_NODE_HANDLE
)PackageNode
,
1035 (AML_NODE_HANDLE
)DataNode
1037 if (EFI_ERROR (Status
)) {
1038 ASSERT_EFI_ERROR (Status
);
1044 Status
= AmlCodeGenInteger (0, &NewElementNode
);
1045 if (EFI_ERROR (Status
)) {
1046 ASSERT_EFI_ERROR (Status
);
1050 Status
= AmlVarListAddTail (
1051 (AML_NODE_HANDLE
)PackageNode
,
1052 (AML_NODE_HANDLE
)NewElementNode
1054 if (EFI_ERROR (Status
)) {
1055 ASSERT_EFI_ERROR (Status
);
1060 Status
= AmlCodeGenInteger (SourceIndex
, &NewElementNode
);
1061 if (EFI_ERROR (Status
)) {
1066 Status
= AmlVarListAddTail (
1067 (AML_NODE_HANDLE
)PackageNode
,
1068 (AML_NODE_HANDLE
)NewElementNode
1070 if (EFI_ERROR (Status
)) {
1075 // Append to the list of _PRT entries.
1076 Status
= AmlVarListAddTail (
1077 (AML_NODE_HANDLE
)PrtEntryList
,
1078 (AML_NODE_HANDLE
)PackageNode
1080 if (EFI_ERROR (Status
)) {
1085 // Free AmlNameString before returning as it is copied
1086 // in the call to AmlCreateDataNode().
1090 AmlDeleteTree ((AML_NODE_HANDLE
)PackageNode
);
1091 if (NewElementNode
!= NULL
) {
1092 AmlDeleteTree ((AML_NODE_HANDLE
)NewElementNode
);
1095 if (DataNode
!= NULL
) {
1096 AmlDeleteTree ((AML_NODE_HANDLE
)DataNode
);
1100 if (AmlNameString
!= NULL
) {
1101 FreePool (AmlNameString
);
1107 /** AML code generation for a Device object node.
1109 AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
1110 equivalent of the following ASL code:
1113 @param [in] NameString The new Device's name.
1114 Must be a NULL-terminated ASL NameString
1115 e.g.: "DEV0", "DV15.DEV0", etc.
1116 The input string is copied.
1117 @param [in] ParentNode If provided, set ParentNode as the parent
1118 of the node created.
1119 @param [out] NewObjectNode If success, contains the created node.
1121 @retval EFI_SUCCESS Success.
1122 @retval EFI_INVALID_PARAMETER Invalid parameter.
1123 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1128 IN CONST CHAR8
*NameString
,
1129 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
1130 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
1134 AML_OBJECT_NODE
*ObjectNode
;
1135 AML_DATA_NODE
*DataNode
;
1136 CHAR8
*AmlNameString
;
1137 UINT32 AmlNameStringSize
;
1139 if ((NameString
== NULL
) ||
1140 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
1143 return EFI_INVALID_PARAMETER
;
1148 AmlNameString
= NULL
;
1150 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1151 if (EFI_ERROR (Status
)) {
1156 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1157 if (EFI_ERROR (Status
)) {
1159 goto error_handler1
;
1162 Status
= AmlCreateObjectNode (
1163 AmlGetByteEncodingByOpCode (AML_EXT_OP
, AML_EXT_DEVICE_OP
),
1164 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
1167 if (EFI_ERROR (Status
)) {
1169 goto error_handler1
;
1172 Status
= AmlCreateDataNode (
1173 EAmlNodeDataTypeNameString
,
1174 (UINT8
*)AmlNameString
,
1178 if (EFI_ERROR (Status
)) {
1180 goto error_handler2
;
1183 Status
= AmlSetFixedArgument (
1185 EAmlParseIndexTerm0
,
1186 (AML_NODE_HEADER
*)DataNode
1188 if (EFI_ERROR (Status
)) {
1190 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
1191 goto error_handler2
;
1199 if (EFI_ERROR (Status
)) {
1201 goto error_handler2
;
1204 // Free AmlNameString before returning as it is copied
1205 // in the call to AmlCreateDataNode().
1206 goto error_handler1
;
1209 if (ObjectNode
!= NULL
) {
1210 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1214 if (AmlNameString
!= NULL
) {
1215 FreePool (AmlNameString
);
1221 /** AML code generation for a Scope object node.
1223 AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
1224 equivalent of the following ASL code:
1227 @param [in] NameString The new Scope's name.
1228 Must be a NULL-terminated ASL NameString
1229 e.g.: "DEV0", "DV15.DEV0", etc.
1230 The input string is copied.
1231 @param [in] ParentNode If provided, set ParentNode as the parent
1232 of the node created.
1233 @param [out] NewObjectNode If success, contains the created node.
1235 @retval EFI_SUCCESS Success.
1236 @retval EFI_INVALID_PARAMETER Invalid parameter.
1237 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1242 IN CONST CHAR8
*NameString
,
1243 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
1244 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
1248 AML_OBJECT_NODE
*ObjectNode
;
1249 AML_DATA_NODE
*DataNode
;
1250 CHAR8
*AmlNameString
;
1251 UINT32 AmlNameStringSize
;
1253 if ((NameString
== NULL
) ||
1254 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
1257 return EFI_INVALID_PARAMETER
;
1262 AmlNameString
= NULL
;
1264 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1265 if (EFI_ERROR (Status
)) {
1270 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1271 if (EFI_ERROR (Status
)) {
1273 goto error_handler1
;
1276 Status
= AmlCreateObjectNode (
1277 AmlGetByteEncodingByOpCode (AML_SCOPE_OP
, 0),
1278 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
1281 if (EFI_ERROR (Status
)) {
1283 goto error_handler1
;
1286 Status
= AmlCreateDataNode (
1287 EAmlNodeDataTypeNameString
,
1288 (UINT8
*)AmlNameString
,
1292 if (EFI_ERROR (Status
)) {
1294 goto error_handler2
;
1297 Status
= AmlSetFixedArgument (
1299 EAmlParseIndexTerm0
,
1300 (AML_NODE_HEADER
*)DataNode
1302 if (EFI_ERROR (Status
)) {
1304 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
1305 goto error_handler2
;
1313 if (EFI_ERROR (Status
)) {
1315 goto error_handler2
;
1318 // Free AmlNameString before returning as it is copied
1319 // in the call to AmlCreateDataNode().
1320 goto error_handler1
;
1323 if (ObjectNode
!= NULL
) {
1324 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1328 if (AmlNameString
!= NULL
) {
1329 FreePool (AmlNameString
);
1335 /** AML code generation for a Method object node.
1337 AmlCodeGenMethod ("MET0", 1, TRUE, 3, ParentNode, NewObjectNode) is
1338 equivalent of the following ASL code:
1339 Method(MET0, 1, Serialized, 3) {}
1341 ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
1342 DefMethod := MethodOp PkgLength NameString MethodFlags TermList
1345 The ASL parameters "ReturnType" and "ParameterTypes" are not asked
1346 in this function. They are optional parameters in ASL.
1348 @param [in] NameString The new Method's name.
1349 Must be a NULL-terminated ASL NameString
1350 e.g.: "MET0", "_SB.MET0", etc.
1351 The input string is copied.
1352 @param [in] NumArgs Number of arguments.
1353 Must be 0 <= NumArgs <= 6.
1354 @param [in] IsSerialized TRUE is equivalent to Serialized.
1355 FALSE is equivalent to NotSerialized.
1356 Default is NotSerialized in ASL spec.
1357 @param [in] SyncLevel Synchronization level for the method.
1358 Must be 0 <= SyncLevel <= 15.
1359 Default is 0 in ASL.
1360 @param [in] ParentNode If provided, set ParentNode as the parent
1361 of the node created.
1362 @param [out] NewObjectNode If success, contains the created node.
1364 @retval EFI_SUCCESS Success.
1365 @retval EFI_INVALID_PARAMETER Invalid parameter.
1366 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1372 IN CONST CHAR8
*NameString
,
1374 IN BOOLEAN IsSerialized
,
1376 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
1377 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
1383 AML_OBJECT_NODE
*ObjectNode
;
1384 AML_DATA_NODE
*DataNode
;
1385 CHAR8
*AmlNameString
;
1386 UINT32 AmlNameStringSize
;
1388 if ((NameString
== NULL
) ||
1391 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
1394 return EFI_INVALID_PARAMETER
;
1400 // ACPI 6.4, s20.2.5.2 "Named Objects Encoding":
1401 // DefMethod := MethodOp PkgLength NameString MethodFlags TermList
1404 // 1- Create the NameString
1405 // 2- Compute the size to write in the PkgLen
1406 // 3- Create nodes for the NameString and Method object node
1407 // 4- Set the NameString DataNode as a fixed argument
1408 // 5- Create and link the MethodFlags node
1410 // 1- Create the NameString
1411 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1412 if (EFI_ERROR (Status
)) {
1417 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1418 if (EFI_ERROR (Status
)) {
1420 goto error_handler1
;
1423 // 2- Compute the size to write in the PkgLen
1424 // Add 1 byte (ByteData) for MethodFlags.
1425 Status
= AmlComputePkgLength (AmlNameStringSize
+ 1, &PkgLen
);
1426 if (EFI_ERROR (Status
)) {
1428 goto error_handler1
;
1431 // 3- Create nodes for the NameString and Method object node
1432 Status
= AmlCreateObjectNode (
1433 AmlGetByteEncodingByOpCode (AML_METHOD_OP
, 0),
1437 if (EFI_ERROR (Status
)) {
1439 goto error_handler1
;
1442 Status
= AmlCreateDataNode (
1443 EAmlNodeDataTypeNameString
,
1444 (UINT8
*)AmlNameString
,
1448 if (EFI_ERROR (Status
)) {
1450 goto error_handler2
;
1453 // 4- Set the NameString DataNode as a fixed argument
1454 Status
= AmlSetFixedArgument (
1456 EAmlParseIndexTerm0
,
1457 (AML_NODE_HEADER
*)DataNode
1459 if (EFI_ERROR (Status
)) {
1461 goto error_handler2
;
1466 // 5- Create and link the MethodFlags node
1468 (IsSerialized
? BIT3
: 0) |
1471 Status
= AmlCreateDataNode (EAmlNodeDataTypeUInt
, &Flags
, 1, &DataNode
);
1472 if (EFI_ERROR (Status
)) {
1474 goto error_handler2
;
1477 Status
= AmlSetFixedArgument (
1479 EAmlParseIndexTerm1
,
1480 (AML_NODE_HEADER
*)DataNode
1482 if (EFI_ERROR (Status
)) {
1484 goto error_handler2
;
1487 // Data node is attached so set the pointer to
1488 // NULL to ensure correct error handling.
1496 if (EFI_ERROR (Status
)) {
1498 goto error_handler2
;
1501 // Free AmlNameString before returning as it is copied
1502 // in the call to AmlCreateDataNode().
1503 goto error_handler1
;
1506 if (ObjectNode
!= NULL
) {
1507 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1510 if (DataNode
!= NULL
) {
1511 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
1515 if (AmlNameString
!= NULL
) {
1516 FreePool (AmlNameString
);
1522 /** AML code generation for a Return object node.
1524 AmlCodeGenReturn (ReturnNode, ParentNode, NewObjectNode) is
1525 equivalent of the following ASL code:
1526 Return([Content of the ReturnNode])
1528 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:
1529 DefReturn := ReturnOp ArgObject
1531 ArgObject := TermArg => DataRefObject
1533 Thus, the ReturnNode must be evaluated as a DataRefObject. It can
1534 be a NameString referencing an object. As this CodeGen Api doesn't
1535 do semantic checking, it is strongly advised to check the AML bytecode
1536 generated by this function against an ASL compiler.
1538 The ReturnNode must be generated inside a Method body scope.
1540 @param [in] ReturnNode The object returned by the Return ASL statement.
1541 This node is deleted if an error occurs.
1542 @param [in] ParentNode If provided, set ParentNode as the parent
1543 of the node created.
1544 Must be a MethodOp node.
1545 @param [out] NewObjectNode If success, contains the created node.
1547 @retval EFI_SUCCESS Success.
1548 @retval EFI_INVALID_PARAMETER Invalid parameter.
1549 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1555 IN AML_NODE_HEADER
*ReturnNode
,
1556 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
1557 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
1561 AML_OBJECT_NODE
*ObjectNode
;
1563 if ((ReturnNode
== NULL
) ||
1564 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)) ||
1565 ((ParentNode
!= NULL
) &&
1566 !AmlNodeCompareOpCode (
1567 (AML_OBJECT_NODE
*)ParentNode
,
1573 return EFI_INVALID_PARAMETER
;
1576 Status
= AmlCreateObjectNode (
1577 AmlGetByteEncodingByOpCode (AML_RETURN_OP
, 0),
1581 if (EFI_ERROR (Status
)) {
1586 Status
= AmlSetFixedArgument (
1588 EAmlParseIndexTerm0
,
1591 if (EFI_ERROR (Status
)) {
1603 if (EFI_ERROR (Status
)) {
1611 if (ReturnNode
!= NULL
) {
1612 AmlDeleteTree (ReturnNode
);
1615 if (ObjectNode
!= NULL
) {
1616 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
1622 /** AML code generation for a Return object node,
1623 returning the object as an input NameString.
1625 AmlCodeGenReturn ("NAM1", ParentNode, NewObjectNode) is
1626 equivalent of the following ASL code:
1629 The ACPI 6.3 specification, s20.2.5.3 "Type 1 Opcodes Encoding" states:
1630 DefReturn := ReturnOp ArgObject
1632 ArgObject := TermArg => DataRefObject
1634 Thus, the ReturnNode must be evaluated as a DataRefObject. It can
1635 be a NameString referencing an object. As this CodeGen Api doesn't
1636 do semantic checking, it is strongly advised to check the AML bytecode
1637 generated by this function against an ASL compiler.
1639 The ReturnNode must be generated inside a Method body scope.
1641 @param [in] NameString The object referenced by this NameString
1642 is returned by the Return ASL statement.
1643 Must be a NULL-terminated ASL NameString
1644 e.g.: "NAM1", "_SB.NAM1", etc.
1645 The input string is copied.
1646 @param [in] ParentNode If provided, set ParentNode as the parent
1647 of the node created.
1648 Must be a MethodOp node.
1649 @param [out] NewObjectNode If success, contains the created node.
1651 @retval EFI_SUCCESS Success.
1652 @retval EFI_INVALID_PARAMETER Invalid parameter.
1653 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1658 AmlCodeGenReturnNameString (
1659 IN CONST CHAR8
*NameString
,
1660 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
1661 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
1665 AML_DATA_NODE
*DataNode
;
1666 CHAR8
*AmlNameString
;
1667 UINT32 AmlNameStringSize
;
1671 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
1672 if (EFI_ERROR (Status
)) {
1677 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
1678 if (EFI_ERROR (Status
)) {
1683 Status
= AmlCreateDataNode (
1684 EAmlNodeDataTypeNameString
,
1685 (UINT8
*)AmlNameString
,
1689 if (EFI_ERROR (Status
)) {
1694 // AmlCodeGenReturn() deletes DataNode if error.
1695 Status
= AmlCodeGenReturn (
1696 (AML_NODE_HEADER
*)DataNode
,
1700 ASSERT_EFI_ERROR (Status
);
1703 if (AmlNameString
!= NULL
) {
1704 FreePool (AmlNameString
);
1710 /** AML code generation for a Return object node,
1711 returning an Integer.
1713 AmlCodeGenReturn (0), ParentNode, NewObjectNode) is
1714 equivalent of the following ASL code:
1717 The ACPI 6.3 specification, 20.2.8 "Statement Opcodes Encoding" states:
1718 DefReturn := ReturnOp ArgObject
1720 ArgObject := TermArg => DataRefObject
1722 Thus, the ReturnNode must be evaluated as a DataRefObject.
1724 The ReturnNode must be generated inside a Method body scope.
1726 @param [in] Integer The integer is returned by the Return
1728 @param [in] ParentNode If provided, set ParentNode as the parent
1729 of the node created.
1730 Must be a MethodOp node.
1731 @param [out] NewObjectNode If success, contains the created node.
1733 @retval EFI_SUCCESS Success.
1734 @retval EFI_INVALID_PARAMETER Invalid parameter.
1735 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1740 AmlCodeGenReturnInteger (
1742 IN AML_NODE_HEADER
*ParentNode OPTIONAL
,
1743 OUT AML_OBJECT_NODE
**NewObjectNode OPTIONAL
1747 AML_OBJECT_NODE
*IntNode
;
1751 Status
= AmlCodeGenInteger (Integer
, &IntNode
);
1752 if (EFI_ERROR (Status
)) {
1757 // AmlCodeGenReturn() deletes DataNode if error.
1758 Status
= AmlCodeGenReturn (
1759 (AML_NODE_HEADER
*)IntNode
,
1763 ASSERT_EFI_ERROR (Status
);
1768 /** AML code generation for a method returning a NameString.
1770 AmlCodeGenMethodRetNameString (
1771 "MET0", "_CRS", 1, TRUE, 3, ParentNode, NewObjectNode
1773 is equivalent of the following ASL code:
1774 Method(MET0, 1, Serialized, 3) {
1778 The ASL parameters "ReturnType" and "ParameterTypes" are not asked
1779 in this function. They are optional parameters in ASL.
1781 @param [in] MethodNameString The new Method's name.
1782 Must be a NULL-terminated ASL NameString
1783 e.g.: "MET0", "_SB.MET0", etc.
1784 The input string is copied.
1785 @param [in] ReturnedNameString The name of the object returned by the
1786 method. Optional parameter, can be:
1788 - A NULL-terminated ASL NameString.
1789 e.g.: "MET0", "_SB.MET0", etc.
1790 The input string is copied.
1791 @param [in] NumArgs Number of arguments.
1792 Must be 0 <= NumArgs <= 6.
1793 @param [in] IsSerialized TRUE is equivalent to Serialized.
1794 FALSE is equivalent to NotSerialized.
1795 Default is NotSerialized in ASL spec.
1796 @param [in] SyncLevel Synchronization level for the method.
1797 Must be 0 <= SyncLevel <= 15.
1798 Default is 0 in ASL.
1799 @param [in] ParentNode If provided, set ParentNode as the parent
1800 of the node created.
1801 @param [out] NewObjectNode If success, contains the created node.
1803 @retval EFI_SUCCESS Success.
1804 @retval EFI_INVALID_PARAMETER Invalid parameter.
1805 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1809 AmlCodeGenMethodRetNameString (
1810 IN CONST CHAR8
*MethodNameString
,
1811 IN CONST CHAR8
*ReturnedNameString OPTIONAL
,
1813 IN BOOLEAN IsSerialized
,
1815 IN AML_NODE_HANDLE ParentNode OPTIONAL
,
1816 OUT AML_OBJECT_NODE_HANDLE
*NewObjectNode OPTIONAL
1820 AML_OBJECT_NODE_HANDLE MethodNode
;
1822 if ((MethodNameString
== NULL
) ||
1823 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
1826 return EFI_INVALID_PARAMETER
;
1829 // Create a Method named MethodNameString.
1830 Status
= AmlCodeGenMethod (
1838 if (EFI_ERROR (Status
)) {
1843 // Return ReturnedNameString if provided.
1844 if (ReturnedNameString
!= NULL
) {
1845 Status
= AmlCodeGenReturnNameString (
1847 (AML_NODE_HANDLE
)MethodNode
,
1850 if (EFI_ERROR (Status
)) {
1861 if (EFI_ERROR (Status
)) {
1869 if (MethodNode
!= NULL
) {
1870 AmlDeleteTree ((AML_NODE_HANDLE
)MethodNode
);
1876 /** AML code generation for a method returning an Integer.
1878 AmlCodeGenMethodRetInteger (
1879 "_CBA", 0, 1, TRUE, 3, ParentNode, NewObjectNode
1881 is equivalent of the following ASL code:
1882 Method(_CBA, 1, Serialized, 3) {
1886 The ASL parameters "ReturnType" and "ParameterTypes" are not asked
1887 in this function. They are optional parameters in ASL.
1889 @param [in] MethodNameString The new Method's name.
1890 Must be a NULL-terminated ASL NameString
1891 e.g.: "MET0", "_SB.MET0", etc.
1892 The input string is copied.
1893 @param [in] ReturnedInteger The value of the integer returned by the
1895 @param [in] NumArgs Number of arguments.
1896 Must be 0 <= NumArgs <= 6.
1897 @param [in] IsSerialized TRUE is equivalent to Serialized.
1898 FALSE is equivalent to NotSerialized.
1899 Default is NotSerialized in ASL spec.
1900 @param [in] SyncLevel Synchronization level for the method.
1901 Must be 0 <= SyncLevel <= 15.
1902 Default is 0 in ASL.
1903 @param [in] ParentNode If provided, set ParentNode as the parent
1904 of the node created.
1905 @param [out] NewObjectNode If success, contains the created node.
1907 @retval EFI_SUCCESS Success.
1908 @retval EFI_INVALID_PARAMETER Invalid parameter.
1909 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1913 AmlCodeGenMethodRetInteger (
1914 IN CONST CHAR8
*MethodNameString
,
1915 IN UINT64 ReturnedInteger
,
1917 IN BOOLEAN IsSerialized
,
1919 IN AML_NODE_HANDLE ParentNode OPTIONAL
,
1920 OUT AML_OBJECT_NODE_HANDLE
*NewObjectNode OPTIONAL
1924 AML_OBJECT_NODE_HANDLE MethodNode
;
1926 if ((MethodNameString
== NULL
) ||
1927 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
)))
1930 return EFI_INVALID_PARAMETER
;
1933 // Create a Method named MethodNameString.
1934 Status
= AmlCodeGenMethod (
1942 if (EFI_ERROR (Status
)) {
1947 Status
= AmlCodeGenReturnInteger (
1949 (AML_NODE_HANDLE
)MethodNode
,
1952 if (EFI_ERROR (Status
)) {
1962 if (EFI_ERROR (Status
)) {
1970 if (MethodNode
!= NULL
) {
1971 AmlDeleteTree ((AML_NODE_HANDLE
)MethodNode
);
1977 /** Create a _LPI name.
1979 AmlCreateLpiNode ("_LPI", 0, 1, ParentNode, &LpiNode) is
1980 equivalent of the following ASL code:
1981 Name (_LPI, Package (
1987 This function doesn't define any LPI state. As shown above, the count
1988 of _LPI state is set to 0.
1989 The AmlAddLpiState () function allows to add LPI states.
1991 Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
1993 @param [in] LpiNameString The new LPI 's object name.
1994 Must be a NULL-terminated ASL NameString
1995 e.g.: "_LPI", "DEV0.PLPI", etc.
1996 The input string is copied.
1997 @param [in] Revision Revision number of the _LPI states.
1998 @param [in] LevelId A platform defined number that identifies the
1999 level of hierarchy of the processor node to
2000 which the LPI states apply.
2001 @param [in] ParentNode If provided, set ParentNode as the parent
2002 of the node created.
2003 @param [out] NewLpiNode If success, contains the created node.
2005 @retval EFI_SUCCESS The function completed successfully.
2006 @retval EFI_INVALID_PARAMETER Invalid parameter.
2007 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2012 IN CONST CHAR8
*LpiNameString
,
2015 IN AML_NODE_HANDLE ParentNode OPTIONAL
,
2016 OUT AML_OBJECT_NODE_HANDLE
*NewLpiNode OPTIONAL
2020 AML_OBJECT_NODE_HANDLE PackageNode
;
2021 AML_OBJECT_NODE_HANDLE IntegerNode
;
2023 if ((LpiNameString
== NULL
) ||
2024 ((ParentNode
== NULL
) && (NewLpiNode
== NULL
)))
2027 return EFI_INVALID_PARAMETER
;
2032 Status
= AmlCodeGenPackage (&PackageNode
);
2033 if (EFI_ERROR (Status
)) {
2038 // Create and attach Revision
2039 Status
= AmlCodeGenInteger (Revision
, &IntegerNode
);
2040 if (EFI_ERROR (Status
)) {
2046 Status
= AmlVarListAddTail (
2047 (AML_NODE_HANDLE
)PackageNode
,
2048 (AML_NODE_HANDLE
)IntegerNode
2050 if (EFI_ERROR (Status
)) {
2057 // Create and attach LevelId
2058 Status
= AmlCodeGenInteger (LevelId
, &IntegerNode
);
2059 if (EFI_ERROR (Status
)) {
2065 Status
= AmlVarListAddTail (
2066 (AML_NODE_HANDLE
)PackageNode
,
2067 (AML_NODE_HANDLE
)IntegerNode
2069 if (EFI_ERROR (Status
)) {
2076 // Create and attach Count. No LPI state is added, so 0.
2077 Status
= AmlCodeGenInteger (0, &IntegerNode
);
2078 if (EFI_ERROR (Status
)) {
2084 Status
= AmlVarListAddTail (
2085 (AML_NODE_HANDLE
)PackageNode
,
2086 (AML_NODE_HANDLE
)IntegerNode
2088 if (EFI_ERROR (Status
)) {
2095 Status
= AmlCodeGenName (LpiNameString
, PackageNode
, ParentNode
, NewLpiNode
);
2096 if (EFI_ERROR (Status
)) {
2104 AmlDeleteTree ((AML_NODE_HANDLE
)PackageNode
);
2105 if (IntegerNode
!= NULL
) {
2106 AmlDeleteTree ((AML_NODE_HANDLE
)IntegerNode
);
2112 /** Add an _LPI state to a LPI node created using AmlCreateLpiNode.
2114 AmlAddLpiState increments the Count of LPI states in the LPI node by one,
2115 and adds the following package:
2118 WorstCaseWakeLatency,
2123 (GenericRegisterDescriptor != NULL) ? // Entry method. If a
2124 ResourceTemplate(GenericRegisterDescriptor) : // Register is given,
2125 Integer, // use it. Use the
2126 // Integer otherwise.
2127 ResourceTemplate() { // NULL Residency Counter
2128 Register (SystemMemory, 0, 0, 0, 0)
2130 ResourceTemplate() { // NULL Usage Counter
2131 Register (SystemMemory, 0, 0, 0, 0)
2133 "" // NULL State Name
2136 Cf ACPI 6.3 specification, s8.4.4 "Lower Power Idle States".
2138 @param [in] MinResidency Minimum Residency.
2139 @param [in] WorstCaseWakeLatency Worst case wake-up latency.
2140 @param [in] Flags Flags.
2141 @param [in] ArchFlags Architectural flags.
2142 @param [in] ResCntFreq Residency Counter Frequency.
2143 @param [in] EnableParentState Enabled Parent State.
2144 @param [in] GenericRegisterDescriptor Entry Method.
2145 If not NULL, use this Register to
2146 describe the entry method address.
2147 @param [in] Integer Entry Method.
2148 If GenericRegisterDescriptor is NULL,
2150 @param [in] ResidencyCounterRegister If not NULL, use it to populate the
2151 residency counter register.
2152 @param [in] UsageCounterRegister If not NULL, use it to populate the
2153 usage counter register.
2154 @param [in] StateName If not NULL, use it to populate the
2156 @param [in] LpiNode Lpi node created with the function
2157 AmlCreateLpiNode to which the new LPI
2160 @retval EFI_SUCCESS The function completed successfully.
2161 @retval EFI_INVALID_PARAMETER Invalid parameter.
2162 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2167 IN UINT32 MinResidency
,
2168 IN UINT32 WorstCaseWakeLatency
,
2170 IN UINT32 ArchFlags
,
2171 IN UINT32 ResCntFreq
,
2172 IN UINT32 EnableParentState
,
2173 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE
*GenericRegisterDescriptor OPTIONAL
,
2174 IN UINT64 Integer OPTIONAL
,
2175 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE
*ResidencyCounterRegister OPTIONAL
,
2176 IN EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE
*UsageCounterRegister OPTIONAL
,
2177 IN CHAR8
*StateName OPTIONAL
,
2178 IN AML_OBJECT_NODE_HANDLE LpiNode
2182 AML_DATA_NODE_HANDLE RdNode
;
2183 AML_OBJECT_NODE_HANDLE PackageNode
;
2184 AML_OBJECT_NODE_HANDLE IntegerNode
;
2185 AML_OBJECT_NODE_HANDLE StringNode
;
2186 AML_OBJECT_NODE_HANDLE NewLpiPackageNode
;
2187 AML_OBJECT_NODE_HANDLE ResourceTemplateNode
;
2190 AML_OBJECT_NODE_HANDLE CountNode
;
2193 if ((LpiNode
== NULL
) ||
2194 (AmlGetNodeType ((AML_NODE_HANDLE
)LpiNode
) != EAmlNodeObject
) ||
2195 (!AmlNodeHasOpCode (LpiNode
, AML_NAME_OP
, 0)))
2198 return EFI_INVALID_PARAMETER
;
2204 ResourceTemplateNode
= NULL
;
2206 // AmlCreateLpiNode () created a LPI container such as:
2207 // Name (_LPI, Package (
2212 // Get the LPI container, a PackageOp object node stored as the 2nd fixed
2213 // argument (i.e. index 1) of LpiNode.
2214 PackageNode
= (AML_OBJECT_NODE_HANDLE
)AmlGetFixedArgument (
2218 if ((PackageNode
== NULL
) ||
2219 (AmlGetNodeType ((AML_NODE_HANDLE
)PackageNode
) != EAmlNodeObject
) ||
2220 (!AmlNodeHasOpCode (PackageNode
, AML_PACKAGE_OP
, 0)))
2223 return EFI_INVALID_PARAMETER
;
2227 // The third variable argument is the LPI Count node.
2228 for (Index
= 0; Index
< 3; Index
++) {
2229 CountNode
= (AML_OBJECT_NODE_HANDLE
)AmlGetNextVariableArgument (
2230 (AML_NODE_HANDLE
)PackageNode
,
2231 (AML_NODE_HANDLE
)CountNode
2233 if (CountNode
== NULL
) {
2235 return EFI_INVALID_PARAMETER
;
2239 Status
= AmlNodeGetIntegerValue (CountNode
, &Count
);
2240 if (EFI_ERROR (Status
)) {
2245 Status
= AmlUpdateInteger (CountNode
, Count
+ 1);
2246 if (EFI_ERROR (Status
)) {
2251 Status
= AmlCodeGenPackage (&NewLpiPackageNode
);
2252 if (EFI_ERROR (Status
)) {
2258 Status
= AmlCodeGenInteger (MinResidency
, &IntegerNode
);
2259 if (EFI_ERROR (Status
)) {
2265 Status
= AmlVarListAddTail (
2266 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2267 (AML_NODE_HANDLE
)IntegerNode
2269 if (EFI_ERROR (Status
)) {
2276 // WorstCaseWakeLatency
2277 Status
= AmlCodeGenInteger (WorstCaseWakeLatency
, &IntegerNode
);
2278 if (EFI_ERROR (Status
)) {
2284 Status
= AmlVarListAddTail (
2285 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2286 (AML_NODE_HANDLE
)IntegerNode
2288 if (EFI_ERROR (Status
)) {
2296 Status
= AmlCodeGenInteger (Flags
, &IntegerNode
);
2297 if (EFI_ERROR (Status
)) {
2303 Status
= AmlVarListAddTail (
2304 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2305 (AML_NODE_HANDLE
)IntegerNode
2307 if (EFI_ERROR (Status
)) {
2315 Status
= AmlCodeGenInteger (ArchFlags
, &IntegerNode
);
2316 if (EFI_ERROR (Status
)) {
2322 Status
= AmlVarListAddTail (
2323 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2324 (AML_NODE_HANDLE
)IntegerNode
2326 if (EFI_ERROR (Status
)) {
2334 Status
= AmlCodeGenInteger (ResCntFreq
, &IntegerNode
);
2335 if (EFI_ERROR (Status
)) {
2341 Status
= AmlVarListAddTail (
2342 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2343 (AML_NODE_HANDLE
)IntegerNode
2345 if (EFI_ERROR (Status
)) {
2352 // EnableParentState
2353 Status
= AmlCodeGenInteger (EnableParentState
, &IntegerNode
);
2354 if (EFI_ERROR (Status
)) {
2360 Status
= AmlVarListAddTail (
2361 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2362 (AML_NODE_HANDLE
)IntegerNode
2364 if (EFI_ERROR (Status
)) {
2372 if (GenericRegisterDescriptor
!= NULL
) {
2373 // Entry Method: As a Register resource data
2374 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
2375 if (EFI_ERROR (Status
)) {
2377 ResourceTemplateNode
= NULL
;
2381 Status
= AmlCodeGenRdRegister (
2382 GenericRegisterDescriptor
->AddressSpaceId
,
2383 GenericRegisterDescriptor
->RegisterBitWidth
,
2384 GenericRegisterDescriptor
->RegisterBitOffset
,
2385 GenericRegisterDescriptor
->Address
,
2386 GenericRegisterDescriptor
->AccessSize
,
2390 if (EFI_ERROR (Status
)) {
2396 Status
= AmlAppendRdNode (ResourceTemplateNode
, RdNode
);
2397 if (EFI_ERROR (Status
)) {
2404 Status
= AmlVarListAddTail (
2405 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2406 (AML_NODE_HANDLE
)ResourceTemplateNode
2408 if (EFI_ERROR (Status
)) {
2413 ResourceTemplateNode
= NULL
;
2415 // Entry Method: As an integer
2416 Status
= AmlCodeGenInteger (Integer
, &IntegerNode
);
2417 if (EFI_ERROR (Status
)) {
2423 Status
= AmlVarListAddTail (
2424 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2425 (AML_NODE_HANDLE
)IntegerNode
2427 if (EFI_ERROR (Status
)) {
2435 // Residency Counter Register.
2436 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
2437 if (EFI_ERROR (Status
)) {
2439 ResourceTemplateNode
= NULL
;
2443 if (ResidencyCounterRegister
!= NULL
) {
2444 Status
= AmlCodeGenRdRegister (
2445 ResidencyCounterRegister
->AddressSpaceId
,
2446 ResidencyCounterRegister
->RegisterBitWidth
,
2447 ResidencyCounterRegister
->RegisterBitOffset
,
2448 ResidencyCounterRegister
->Address
,
2449 ResidencyCounterRegister
->AccessSize
,
2454 Status
= AmlCodeGenRdRegister (
2455 EFI_ACPI_6_4_SYSTEM_MEMORY
,
2465 if (EFI_ERROR (Status
)) {
2471 Status
= AmlAppendRdNode (ResourceTemplateNode
, RdNode
);
2472 if (EFI_ERROR (Status
)) {
2479 Status
= AmlVarListAddTail (
2480 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2481 (AML_NODE_HANDLE
)ResourceTemplateNode
2483 if (EFI_ERROR (Status
)) {
2488 ResourceTemplateNode
= NULL
;
2490 // Usage Counter Register.
2491 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
2492 if (EFI_ERROR (Status
)) {
2494 ResourceTemplateNode
= NULL
;
2498 if (UsageCounterRegister
!= NULL
) {
2499 Status
= AmlCodeGenRdRegister (
2500 UsageCounterRegister
->AddressSpaceId
,
2501 UsageCounterRegister
->RegisterBitWidth
,
2502 UsageCounterRegister
->RegisterBitOffset
,
2503 UsageCounterRegister
->Address
,
2504 UsageCounterRegister
->AccessSize
,
2509 Status
= AmlCodeGenRdRegister (
2510 EFI_ACPI_6_4_SYSTEM_MEMORY
,
2520 if (EFI_ERROR (Status
)) {
2526 Status
= AmlAppendRdNode (ResourceTemplateNode
, RdNode
);
2527 if (EFI_ERROR (Status
)) {
2534 Status
= AmlVarListAddTail (
2535 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2536 (AML_NODE_HANDLE
)ResourceTemplateNode
2538 if (EFI_ERROR (Status
)) {
2543 ResourceTemplateNode
= NULL
;
2546 if (UsageCounterRegister
!= NULL
) {
2547 Status
= AmlCodeGenString (StateName
, &StringNode
);
2549 Status
= AmlCodeGenString ("", &StringNode
);
2552 if (EFI_ERROR (Status
)) {
2558 Status
= AmlVarListAddTail (
2559 (AML_NODE_HANDLE
)NewLpiPackageNode
,
2560 (AML_NODE_HANDLE
)StringNode
2562 if (EFI_ERROR (Status
)) {
2569 // Add the new LPI state to the LpiNode.
2570 Status
= AmlVarListAddTail (
2571 (AML_NODE_HANDLE
)PackageNode
,
2572 (AML_NODE_HANDLE
)NewLpiPackageNode
2574 if (EFI_ERROR (Status
)) {
2582 if (RdNode
!= NULL
) {
2583 AmlDeleteTree ((AML_NODE_HANDLE
)RdNode
);
2586 if (NewLpiPackageNode
!= NULL
) {
2587 AmlDeleteTree ((AML_NODE_HANDLE
)NewLpiPackageNode
);
2590 if (StringNode
!= NULL
) {
2591 AmlDeleteTree ((AML_NODE_HANDLE
)StringNode
);
2594 if (IntegerNode
!= NULL
) {
2595 AmlDeleteTree ((AML_NODE_HANDLE
)IntegerNode
);
2598 if (ResourceTemplateNode
!= NULL
) {
2599 AmlDeleteTree ((AML_NODE_HANDLE
)ResourceTemplateNode
);
2605 /** AML code generation for a _DSD device data object.
2607 AmlAddDeviceDataDescriptorPackage (Uuid, DsdNode, PackageNode) is
2608 equivalent of the following ASL code:
2612 Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)".
2614 _DSD (Device Specific Data) Implementation Guide
2615 https://github.com/UEFI/DSD-Guide
2616 Per s3. "'Well-Known _DSD UUIDs and Data Structure Formats'"
2617 If creating a Device Properties data then UUID daffd814-6eba-4d8c-8a91-bc9bbf4aa301 should be used.
2619 @param [in] Uuid The Uuid of the descriptor to be created
2620 @param [in] DsdNode Node of the DSD Package.
2621 @param [out] PackageNode If success, contains the created package node.
2623 @retval EFI_SUCCESS Success.
2624 @retval EFI_INVALID_PARAMETER Invalid parameter.
2625 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2629 AmlAddDeviceDataDescriptorPackage (
2630 IN CONST EFI_GUID
*Uuid
,
2631 IN AML_OBJECT_NODE_HANDLE DsdNode
,
2632 OUT AML_OBJECT_NODE_HANDLE
*PackageNode
2636 AML_OBJECT_NODE
*UuidNode
;
2637 AML_DATA_NODE
*UuidDataNode
;
2638 AML_OBJECT_NODE_HANDLE DsdEntryList
;
2640 if ((Uuid
== NULL
) ||
2641 (PackageNode
== NULL
) ||
2642 (AmlGetNodeType ((AML_NODE_HANDLE
)DsdNode
) != EAmlNodeObject
) ||
2643 (!AmlNodeHasOpCode (DsdNode
, AML_NAME_OP
, 0)) ||
2644 !AmlNameOpCompareName (DsdNode
, "_DSD"))
2646 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
2647 return EFI_INVALID_PARAMETER
;
2650 // Get the Package object node of the _DSD node,
2651 // which is the 2nd fixed argument (i.e. index 1).
2652 DsdEntryList
= (AML_OBJECT_NODE_HANDLE
)AmlGetFixedArgument (
2656 if ((DsdEntryList
== NULL
) ||
2657 (AmlGetNodeType ((AML_NODE_HANDLE
)DsdEntryList
) != EAmlNodeObject
) ||
2658 (!AmlNodeHasOpCode (DsdEntryList
, AML_PACKAGE_OP
, 0)))
2660 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
2661 return EFI_INVALID_PARAMETER
;
2664 *PackageNode
= NULL
;
2665 UuidDataNode
= NULL
;
2667 Status
= AmlCodeGenBuffer (NULL
, 0, &UuidNode
);
2668 if (EFI_ERROR (Status
)) {
2669 ASSERT_EFI_ERROR (Status
);
2673 Status
= AmlCreateDataNode (
2674 EAmlNodeDataTypeRaw
,
2675 (CONST UINT8
*)Uuid
,
2679 if (EFI_ERROR (Status
)) {
2680 ASSERT_EFI_ERROR (Status
);
2684 Status
= AmlVarListAddTail (
2685 (AML_NODE_HEADER
*)UuidNode
,
2686 (AML_NODE_HEADER
*)UuidDataNode
2688 if (EFI_ERROR (Status
)) {
2689 ASSERT_EFI_ERROR (Status
);
2693 UuidDataNode
= NULL
;
2695 // Append to the list of _DSD entries.
2696 Status
= AmlVarListAddTail (
2697 (AML_NODE_HANDLE
)DsdEntryList
,
2698 (AML_NODE_HANDLE
)UuidNode
2700 if (EFI_ERROR (Status
)) {
2701 ASSERT_EFI_ERROR (Status
);
2705 Status
= AmlCodeGenPackage (PackageNode
);
2706 if (EFI_ERROR (Status
)) {
2707 ASSERT_EFI_ERROR (Status
);
2708 goto error_handler_detach
;
2711 // Append to the list of _DSD entries.
2712 Status
= AmlVarListAddTail (
2713 (AML_NODE_HANDLE
)DsdEntryList
,
2714 (AML_NODE_HANDLE
)*PackageNode
2716 if (EFI_ERROR (Status
)) {
2717 ASSERT_EFI_ERROR (Status
);
2718 goto error_handler_detach
;
2723 error_handler_detach
:
2724 if (UuidNode
!= NULL
) {
2725 AmlDetachNode ((AML_NODE_HANDLE
)UuidNode
);
2729 if (UuidNode
!= NULL
) {
2730 AmlDeleteTree ((AML_NODE_HANDLE
)UuidNode
);
2733 if (*PackageNode
!= NULL
) {
2734 AmlDeleteTree ((AML_NODE_HANDLE
)*PackageNode
);
2735 *PackageNode
= NULL
;
2738 if (UuidDataNode
!= NULL
) {
2739 AmlDeleteTree ((AML_NODE_HANDLE
)UuidDataNode
);
2745 /** AML code generation to add a package with a name and value,
2746 to a parent package.
2747 This is useful to build the _DSD package but can be used in other cases.
2749 AmlAddNameIntegerPackage ("Name", Value, PackageNode) is
2750 equivalent of the following ASL code:
2751 Package (2) {"Name", Value}
2753 Cf ACPI 6.4 specification, s6.2.5 "_DSD (Device Specific Data)".
2755 @param [in] Name String to place in first entry of package
2756 @param [in] Value Integer to place in second entry of package
2757 @param [in] PackageNode Package to add new sub package to.
2759 @retval EFI_SUCCESS Success.
2760 @retval EFI_INVALID_PARAMETER Invalid parameter.
2761 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2765 AmlAddNameIntegerPackage (
2768 IN AML_OBJECT_NODE_HANDLE PackageNode
2772 AML_OBJECT_NODE
*NameNode
;
2773 AML_OBJECT_NODE
*ValueNode
;
2774 AML_OBJECT_NODE
*NewPackageNode
;
2776 if ((Name
== NULL
) ||
2777 (AmlGetNodeType ((AML_NODE_HANDLE
)PackageNode
) != EAmlNodeObject
) ||
2778 (!AmlNodeHasOpCode (PackageNode
, AML_PACKAGE_OP
, 0)))
2780 ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER
);
2781 return EFI_INVALID_PARAMETER
;
2787 // The new package entry.
2788 Status
= AmlCodeGenPackage (&NewPackageNode
);
2789 if (EFI_ERROR (Status
)) {
2790 ASSERT_EFI_ERROR (Status
);
2794 Status
= AmlCodeGenString (Name
, &NameNode
);
2795 if (EFI_ERROR (Status
)) {
2796 ASSERT_EFI_ERROR (Status
);
2800 Status
= AmlVarListAddTail (
2801 (AML_NODE_HANDLE
)NewPackageNode
,
2802 (AML_NODE_HANDLE
)NameNode
2804 if (EFI_ERROR (Status
)) {
2805 ASSERT_EFI_ERROR (Status
);
2811 Status
= AmlCodeGenInteger (Value
, &ValueNode
);
2812 if (EFI_ERROR (Status
)) {
2813 ASSERT_EFI_ERROR (Status
);
2817 Status
= AmlVarListAddTail (
2818 (AML_NODE_HANDLE
)NewPackageNode
,
2819 (AML_NODE_HANDLE
)ValueNode
2821 if (EFI_ERROR (Status
)) {
2822 ASSERT_EFI_ERROR (Status
);
2828 Status
= AmlVarListAddTail (
2829 (AML_NODE_HANDLE
)PackageNode
,
2830 (AML_NODE_HANDLE
)NewPackageNode
2832 if (EFI_ERROR (Status
)) {
2833 ASSERT_EFI_ERROR (Status
);
2840 if (NewPackageNode
!= NULL
) {
2841 AmlDeleteTree ((AML_NODE_HANDLE
)NewPackageNode
);
2844 if (NameNode
!= NULL
) {
2845 AmlDeleteTree ((AML_NODE_HANDLE
)NameNode
);
2848 if (ValueNode
!= NULL
) {
2849 AmlDeleteTree ((AML_NODE_HANDLE
)ValueNode
);
2855 /** Adds a register to the package
2857 @ingroup CodeGenApis
2859 @param [in] Register If provided, register that will be added to package.
2860 otherwise NULL register will be added
2861 @param [in] PackageNode Package to add value to
2863 @retval EFI_SUCCESS The function completed successfully.
2864 @retval EFI_INVALID_PARAMETER Invalid parameter.
2865 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2870 AmlAddRegisterToPackage (
2871 IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE
*Register OPTIONAL
,
2872 IN AML_OBJECT_NODE_HANDLE PackageNode
2876 AML_DATA_NODE_HANDLE RdNode
;
2877 AML_OBJECT_NODE_HANDLE ResourceTemplateNode
;
2881 Status
= AmlCodeGenResourceTemplate (&ResourceTemplateNode
);
2882 if (EFI_ERROR (Status
)) {
2883 ASSERT_EFI_ERROR (Status
);
2887 if (Register
!= NULL
) {
2888 Status
= AmlCodeGenRdRegister (
2889 Register
->AddressSpaceId
,
2890 Register
->RegisterBitWidth
,
2891 Register
->RegisterBitOffset
,
2893 Register
->AccessSize
,
2898 Status
= AmlCodeGenRdRegister (
2899 EFI_ACPI_6_4_SYSTEM_MEMORY
,
2909 if (EFI_ERROR (Status
)) {
2910 ASSERT_EFI_ERROR (Status
);
2914 Status
= AmlAppendRdNode (ResourceTemplateNode
, RdNode
);
2915 if (EFI_ERROR (Status
)) {
2916 ASSERT_EFI_ERROR (Status
);
2922 Status
= AmlVarListAddTail (
2923 (AML_NODE_HANDLE
)PackageNode
,
2924 (AML_NODE_HANDLE
)ResourceTemplateNode
2926 if (EFI_ERROR (Status
)) {
2927 ASSERT_EFI_ERROR (Status
);
2934 if (RdNode
!= NULL
) {
2935 AmlDeleteTree ((AML_NODE_HANDLE
)RdNode
);
2938 if (ResourceTemplateNode
!= NULL
) {
2939 AmlDeleteTree ((AML_NODE_HANDLE
)ResourceTemplateNode
);
2945 /** Utility function to check if generic address points to NULL
2947 @param [in] Address Pointer to the Generic address
2949 @retval TRUE Address is system memory with an Address of 0.
2950 @retval FALSE Address does not point to NULL.
2955 IsNullGenericAddress (
2956 IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE
*Address
2959 if ((Address
== NULL
) ||
2960 ((Address
->AddressSpaceId
== EFI_ACPI_6_4_SYSTEM_MEMORY
) &&
2961 (Address
->Address
== 0x0)))
2969 /** Adds an integer or register to the package
2971 @ingroup CodeGenApis
2973 @param [in] Register If provided, register that will be added to package
2974 @param [in] Integer If Register is NULL, integer that will be added to the package
2975 @param [in] PackageNode Package to add value to
2977 @retval EFI_SUCCESS The function completed successfully.
2978 @retval EFI_INVALID_PARAMETER Invalid parameter.
2979 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
2984 AmlAddRegisterOrIntegerToPackage (
2985 IN EFI_ACPI_6_4_GENERIC_ADDRESS_STRUCTURE
*Register OPTIONAL
,
2987 IN AML_OBJECT_NODE_HANDLE PackageNode
2991 AML_OBJECT_NODE_HANDLE IntegerNode
;
2995 if (!IsNullGenericAddress (Register
)) {
2996 Status
= AmlAddRegisterToPackage (Register
, PackageNode
);
2998 Status
= AmlCodeGenInteger (Integer
, &IntegerNode
);
2999 if (EFI_ERROR (Status
)) {
3000 ASSERT_EFI_ERROR (Status
);
3004 Status
= AmlVarListAddTail (
3005 (AML_NODE_HANDLE
)PackageNode
,
3006 (AML_NODE_HANDLE
)IntegerNode
3010 if (EFI_ERROR (Status
)) {
3011 ASSERT_EFI_ERROR (Status
);
3012 if (IntegerNode
!= NULL
) {
3013 AmlDeleteTree ((AML_NODE_HANDLE
)IntegerNode
);
3020 /** Create a _CPC node.
3022 Creates and optionally adds the following node
3023 Name(_CPC, Package()
3025 NumEntries, // Integer
3026 Revision, // Integer
3027 HighestPerformance, // Integer or Buffer (Resource Descriptor)
3028 NominalPerformance, // Integer or Buffer (Resource Descriptor)
3029 LowestNonlinearPerformance, // Integer or Buffer (Resource Descriptor)
3030 LowestPerformance, // Integer or Buffer (Resource Descriptor)
3031 GuaranteedPerformanceRegister, // Buffer (Resource Descriptor)
3032 DesiredPerformanceRegister , // Buffer (Resource Descriptor)
3033 MinimumPerformanceRegister , // Buffer (Resource Descriptor)
3034 MaximumPerformanceRegister , // Buffer (Resource Descriptor)
3035 PerformanceReductionToleranceRegister, // Buffer (Resource Descriptor)
3036 TimeWindowRegister, // Buffer (Resource Descriptor)
3037 CounterWraparoundTime, // Integer or Buffer (Resource Descriptor)
3038 ReferencePerformanceCounterRegister, // Buffer (Resource Descriptor)
3039 DeliveredPerformanceCounterRegister, // Buffer (Resource Descriptor)
3040 PerformanceLimitedRegister, // Buffer (Resource Descriptor)
3041 CPPCEnableRegister // Buffer (Resource Descriptor)
3042 AutonomousSelectionEnable, // Integer or Buffer (Resource Descriptor)
3043 AutonomousActivityWindowRegister, // Buffer (Resource Descriptor)
3044 EnergyPerformancePreferenceRegister, // Buffer (Resource Descriptor)
3045 ReferencePerformance // Integer or Buffer (Resource Descriptor)
3046 LowestFrequency, // Integer or Buffer (Resource Descriptor)
3047 NominalFrequency // Integer or Buffer (Resource Descriptor)
3050 If resource buffer is NULL then integer will be used.
3052 Cf. ACPI 6.4, s8.4.7.1 _CPC (Continuous Performance Control)
3054 @ingroup CodeGenApis
3056 @param [in] CpcInfo CpcInfo object
3057 @param [in] ParentNode If provided, set ParentNode as the parent
3058 of the node created.
3059 @param [out] NewCpcNode If success and provided, contains the created node.
3061 @retval EFI_SUCCESS The function completed successfully.
3062 @retval EFI_INVALID_PARAMETER Invalid parameter.
3063 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
3068 IN AML_CPC_INFO
*CpcInfo
,
3069 IN AML_NODE_HANDLE ParentNode OPTIONAL
,
3070 OUT AML_OBJECT_NODE_HANDLE
*NewCpcNode OPTIONAL
3074 AML_OBJECT_NODE_HANDLE CpcNode
;
3075 AML_OBJECT_NODE_HANDLE CpcPackage
;
3076 UINT32 NumberOfEntries
;
3078 if ((CpcInfo
== NULL
) ||
3079 ((ParentNode
== NULL
) && (NewCpcNode
== NULL
)))
3082 return EFI_INVALID_PARAMETER
;
3085 // Revision 3 per ACPI 6.4 specification
3086 if (CpcInfo
->Revision
== 3) {
3087 // NumEntries 23 per ACPI 6.4 specification
3088 NumberOfEntries
= 23;
3091 return EFI_INVALID_PARAMETER
;
3094 if ((IsNullGenericAddress (&CpcInfo
->HighestPerformanceBuffer
) &&
3095 (CpcInfo
->HighestPerformanceInteger
== 0)) ||
3096 (IsNullGenericAddress (&CpcInfo
->NominalPerformanceBuffer
) &&
3097 (CpcInfo
->NominalPerformanceInteger
== 0)) ||
3098 (IsNullGenericAddress (&CpcInfo
->LowestNonlinearPerformanceBuffer
) &&
3099 (CpcInfo
->LowestNonlinearPerformanceInteger
== 0)) ||
3100 (IsNullGenericAddress (&CpcInfo
->LowestPerformanceBuffer
) &&
3101 (CpcInfo
->LowestPerformanceInteger
== 0)) ||
3102 IsNullGenericAddress (&CpcInfo
->DesiredPerformanceRegister
) ||
3103 IsNullGenericAddress (&CpcInfo
->ReferencePerformanceCounterRegister
) ||
3104 IsNullGenericAddress (&CpcInfo
->DeliveredPerformanceCounterRegister
) ||
3105 IsNullGenericAddress (&CpcInfo
->PerformanceLimitedRegister
))
3108 return EFI_INVALID_PARAMETER
;
3113 Status
= AmlCodeGenNamePackage ("_CPC", NULL
, &CpcNode
);
3114 if (EFI_ERROR (Status
)) {
3115 ASSERT_EFI_ERROR (Status
);
3119 // Get the Package object node of the _CPC node,
3120 // which is the 2nd fixed argument (i.e. index 1).
3121 CpcPackage
= (AML_OBJECT_NODE_HANDLE
)AmlGetFixedArgument (
3125 if ((CpcPackage
== NULL
) ||
3126 (AmlGetNodeType ((AML_NODE_HANDLE
)CpcPackage
) != EAmlNodeObject
) ||
3127 (!AmlNodeHasOpCode (CpcPackage
, AML_PACKAGE_OP
, 0)))
3130 Status
= EFI_INVALID_PARAMETER
;
3134 Status
= AmlAddRegisterOrIntegerToPackage (
3139 if (EFI_ERROR (Status
)) {
3140 ASSERT_EFI_ERROR (Status
);
3144 Status
= AmlAddRegisterOrIntegerToPackage (
3149 if (EFI_ERROR (Status
)) {
3150 ASSERT_EFI_ERROR (Status
);
3154 Status
= AmlAddRegisterOrIntegerToPackage (
3155 &CpcInfo
->HighestPerformanceBuffer
,
3156 CpcInfo
->HighestPerformanceInteger
,
3159 if (EFI_ERROR (Status
)) {
3160 ASSERT_EFI_ERROR (Status
);
3164 Status
= AmlAddRegisterOrIntegerToPackage (
3165 &CpcInfo
->NominalPerformanceBuffer
,
3166 CpcInfo
->NominalPerformanceInteger
,
3169 if (EFI_ERROR (Status
)) {
3170 ASSERT_EFI_ERROR (Status
);
3174 Status
= AmlAddRegisterOrIntegerToPackage (
3175 &CpcInfo
->LowestNonlinearPerformanceBuffer
,
3176 CpcInfo
->LowestNonlinearPerformanceInteger
,
3179 if (EFI_ERROR (Status
)) {
3180 ASSERT_EFI_ERROR (Status
);
3184 Status
= AmlAddRegisterOrIntegerToPackage (
3185 &CpcInfo
->LowestPerformanceBuffer
,
3186 CpcInfo
->LowestPerformanceInteger
,
3189 if (EFI_ERROR (Status
)) {
3190 ASSERT_EFI_ERROR (Status
);
3194 Status
= AmlAddRegisterToPackage (&CpcInfo
->GuaranteedPerformanceRegister
, CpcPackage
);
3195 if (EFI_ERROR (Status
)) {
3196 ASSERT_EFI_ERROR (Status
);
3200 Status
= AmlAddRegisterToPackage (&CpcInfo
->DesiredPerformanceRegister
, CpcPackage
);
3201 if (EFI_ERROR (Status
)) {
3202 ASSERT_EFI_ERROR (Status
);
3206 Status
= AmlAddRegisterToPackage (&CpcInfo
->MinimumPerformanceRegister
, CpcPackage
);
3207 if (EFI_ERROR (Status
)) {
3208 ASSERT_EFI_ERROR (Status
);
3212 Status
= AmlAddRegisterToPackage (&CpcInfo
->MaximumPerformanceRegister
, CpcPackage
);
3213 if (EFI_ERROR (Status
)) {
3214 ASSERT_EFI_ERROR (Status
);
3218 Status
= AmlAddRegisterToPackage (&CpcInfo
->PerformanceReductionToleranceRegister
, CpcPackage
);
3219 if (EFI_ERROR (Status
)) {
3220 ASSERT_EFI_ERROR (Status
);
3224 Status
= AmlAddRegisterToPackage (&CpcInfo
->TimeWindowRegister
, CpcPackage
);
3225 if (EFI_ERROR (Status
)) {
3226 ASSERT_EFI_ERROR (Status
);
3230 Status
= AmlAddRegisterOrIntegerToPackage (
3231 &CpcInfo
->CounterWraparoundTimeBuffer
,
3232 CpcInfo
->CounterWraparoundTimeInteger
,
3235 if (EFI_ERROR (Status
)) {
3236 ASSERT_EFI_ERROR (Status
);
3240 Status
= AmlAddRegisterToPackage (&CpcInfo
->ReferencePerformanceCounterRegister
, CpcPackage
);
3241 if (EFI_ERROR (Status
)) {
3242 ASSERT_EFI_ERROR (Status
);
3246 Status
= AmlAddRegisterToPackage (&CpcInfo
->DeliveredPerformanceCounterRegister
, CpcPackage
);
3247 if (EFI_ERROR (Status
)) {
3248 ASSERT_EFI_ERROR (Status
);
3252 Status
= AmlAddRegisterToPackage (&CpcInfo
->PerformanceLimitedRegister
, CpcPackage
);
3253 if (EFI_ERROR (Status
)) {
3254 ASSERT_EFI_ERROR (Status
);
3258 Status
= AmlAddRegisterToPackage (&CpcInfo
->CPPCEnableRegister
, CpcPackage
);
3259 if (EFI_ERROR (Status
)) {
3260 ASSERT_EFI_ERROR (Status
);
3264 Status
= AmlAddRegisterOrIntegerToPackage (
3265 &CpcInfo
->AutonomousSelectionEnableBuffer
,
3266 CpcInfo
->AutonomousSelectionEnableInteger
,
3269 if (EFI_ERROR (Status
)) {
3270 ASSERT_EFI_ERROR (Status
);
3274 Status
= AmlAddRegisterToPackage (&CpcInfo
->AutonomousActivityWindowRegister
, CpcPackage
);
3275 if (EFI_ERROR (Status
)) {
3276 ASSERT_EFI_ERROR (Status
);
3280 Status
= AmlAddRegisterToPackage (&CpcInfo
->EnergyPerformancePreferenceRegister
, CpcPackage
);
3281 if (EFI_ERROR (Status
)) {
3282 ASSERT_EFI_ERROR (Status
);
3286 Status
= AmlAddRegisterOrIntegerToPackage (
3287 &CpcInfo
->ReferencePerformanceBuffer
,
3288 CpcInfo
->ReferencePerformanceInteger
,
3291 if (EFI_ERROR (Status
)) {
3292 ASSERT_EFI_ERROR (Status
);
3296 Status
= AmlAddRegisterOrIntegerToPackage (
3297 &CpcInfo
->LowestFrequencyBuffer
,
3298 CpcInfo
->LowestFrequencyInteger
,
3301 if (EFI_ERROR (Status
)) {
3302 ASSERT_EFI_ERROR (Status
);
3306 Status
= AmlAddRegisterOrIntegerToPackage (
3307 &CpcInfo
->NominalFrequencyBuffer
,
3308 CpcInfo
->NominalFrequencyInteger
,
3311 if (EFI_ERROR (Status
)) {
3312 ASSERT_EFI_ERROR (Status
);
3316 Status
= LinkNode (CpcNode
, ParentNode
, NewCpcNode
);
3317 if (EFI_ERROR (Status
)) {
3318 ASSERT_EFI_ERROR (Status
);
3325 AmlDeleteTree ((AML_NODE_HANDLE
)CpcNode
);