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 <Tree/AmlNode.h>
16 #include <Tree/AmlTree.h>
17 #include <String/AmlString.h>
18 #include <Utils/AmlUtility.h>
20 /** Utility function to link a node when returning from a CodeGen function.
22 @param [in] Node Newly created node.
23 @param [in] ParentNode If provided, set ParentNode as the parent
25 @param [out] NewObjectNode If not NULL:
26 - and Success, contains the created Node.
27 - and Error, reset to NULL.
29 @retval EFI_SUCCESS The function completed successfully.
30 @retval EFI_INVALID_PARAMETER Invalid parameter.
36 IN AML_OBJECT_NODE
* Node
,
37 IN AML_NODE_HEADER
* ParentNode
,
38 OUT AML_OBJECT_NODE
** NewObjectNode
43 if (NewObjectNode
!= NULL
) {
44 *NewObjectNode
= NULL
;
47 // Add RdNode as the last element.
48 if (ParentNode
!= NULL
) {
49 Status
= AmlVarListAddTail (ParentNode
, (AML_NODE_HEADER
*)Node
);
50 if (EFI_ERROR (Status
)) {
56 if (NewObjectNode
!= NULL
) {
57 *NewObjectNode
= Node
;
63 /** AML code generation for DefinitionBlock.
65 Create a Root Node handle.
66 It is the caller's responsibility to free the allocated memory
67 with the AmlDeleteTree function.
69 AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
70 equivalent to the following ASL code:
71 DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
72 OemID, TableID, OEMRevision) {}
73 with the ComplianceRevision set to 2 and the AMLFileName is ignored.
75 @param[in] TableSignature 4-character ACPI signature.
76 Must be 'DSDT' or 'SSDT'.
77 @param[in] OemId 6-character string OEM identifier.
78 @param[in] OemTableId 8-character string OEM table identifier.
79 @param[in] OemRevision OEM revision number.
80 @param[out] NewRootNode Pointer to the root node representing a
83 @retval EFI_SUCCESS Success.
84 @retval EFI_INVALID_PARAMETER Invalid parameter.
85 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
89 AmlCodeGenDefinitionBlock (
90 IN CONST CHAR8
* TableSignature
,
91 IN CONST CHAR8
* OemId
,
92 IN CONST CHAR8
* OemTableId
,
93 IN UINT32 OemRevision
,
94 OUT AML_ROOT_NODE
** NewRootNode
98 EFI_ACPI_DESCRIPTION_HEADER AcpiHeader
;
100 if ((TableSignature
== NULL
) ||
102 (OemTableId
== NULL
) ||
103 (NewRootNode
== NULL
)) {
105 return EFI_INVALID_PARAMETER
;
108 CopyMem (&AcpiHeader
.Signature
, TableSignature
, 4);
109 AcpiHeader
.Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
110 AcpiHeader
.Revision
= 2;
111 CopyMem (&AcpiHeader
.OemId
, OemId
, 6);
112 CopyMem (&AcpiHeader
.OemTableId
, OemTableId
, 8);
113 AcpiHeader
.OemRevision
= OemRevision
;
114 AcpiHeader
.CreatorId
= TABLE_GENERATOR_CREATOR_ID_ARM
;
115 AcpiHeader
.CreatorRevision
= CREATE_REVISION (1, 0);
117 Status
= AmlCreateRootNode (&AcpiHeader
, NewRootNode
);
118 ASSERT_EFI_ERROR (Status
);
123 /** AML code generation for a String object node.
125 @param [in] String Pointer to a NULL terminated string.
126 @param [out] NewObjectNode If success, contains the created
129 @retval EFI_SUCCESS Success.
130 @retval EFI_INVALID_PARAMETER Invalid parameter.
131 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
138 OUT AML_OBJECT_NODE
** NewObjectNode
142 AML_OBJECT_NODE
* ObjectNode
;
143 AML_DATA_NODE
* DataNode
;
145 if ((String
== NULL
) ||
146 (NewObjectNode
== NULL
)) {
148 return EFI_INVALID_PARAMETER
;
153 Status
= AmlCreateObjectNode (
154 AmlGetByteEncodingByOpCode (AML_STRING_PREFIX
, 0),
158 if (EFI_ERROR (Status
)) {
163 Status
= AmlCreateDataNode (
164 EAmlNodeDataTypeString
,
166 (UINT32
)AsciiStrLen (String
) + 1,
169 if (EFI_ERROR (Status
)) {
174 Status
= AmlSetFixedArgument (
177 (AML_NODE_HEADER
*)DataNode
179 if (EFI_ERROR (Status
)) {
181 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
185 *NewObjectNode
= ObjectNode
;
189 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
193 /** AML code generation for an Integer object node.
195 @param [in] Integer Integer of the Integer object node.
196 @param [out] NewObjectNode If success, contains the created
199 @retval EFI_SUCCESS Success.
200 @retval EFI_INVALID_PARAMETER Invalid parameter.
201 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
208 OUT AML_OBJECT_NODE
** NewObjectNode
214 if (NewObjectNode
== NULL
) {
216 return EFI_INVALID_PARAMETER
;
219 // Create an object node containing Zero.
220 Status
= AmlCreateObjectNode (
221 AmlGetByteEncodingByOpCode (AML_ZERO_OP
, 0),
225 if (EFI_ERROR (Status
)) {
230 // Update the object node with integer value.
231 Status
= AmlNodeSetIntegerValue (*NewObjectNode
, Integer
, &ValueWidthDiff
);
232 if (EFI_ERROR (Status
)) {
234 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
240 /** AML code generation for a Package object node.
242 The package generated is empty. New elements can be added via its
243 list of variable arguments.
245 @param [out] NewObjectNode If success, contains the created
248 @retval EFI_SUCCESS Success.
249 @retval EFI_INVALID_PARAMETER Invalid parameter.
250 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
256 OUT AML_OBJECT_NODE
** NewObjectNode
260 AML_DATA_NODE
* DataNode
;
263 if (NewObjectNode
== NULL
) {
265 return EFI_INVALID_PARAMETER
;
270 // Create an object node.
272 // - one byte to store the PkgLength
273 // - one byte for the NumElements.
274 // Cf ACPI6.3, s20.2.5 "Term Objects Encoding"
275 // DefPackage := PackageOp PkgLength NumElements PackageElementList
276 // NumElements := ByteData
277 Status
= AmlCreateObjectNode (
278 AmlGetByteEncodingByOpCode (AML_PACKAGE_OP
, 0),
282 if (EFI_ERROR (Status
)) {
287 // NumElements is a ByteData.
288 Status
= AmlCreateDataNode (
289 EAmlNodeDataTypeUInt
,
294 if (EFI_ERROR (Status
)) {
299 Status
= AmlSetFixedArgument (
302 (AML_NODE_HEADER
*)DataNode
304 if (EFI_ERROR (Status
)) {
312 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
313 if (DataNode
!= NULL
) {
314 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
319 /** AML code generation for a Name object node.
321 @param [in] NameString The new variable name.
322 Must be a NULL-terminated ASL NameString
323 e.g.: "DEV0", "DV15.DEV0", etc.
324 This input string is copied.
325 @param [in] Object Object associated to the NameString.
326 @param [in] ParentNode If provided, set ParentNode as the parent
328 @param [out] NewObjectNode If success, contains the created node.
330 @retval EFI_SUCCESS Success.
331 @retval EFI_INVALID_PARAMETER Invalid parameter.
332 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
338 IN CONST CHAR8
* NameString
,
339 IN AML_OBJECT_NODE
* Object
,
340 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
341 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
345 AML_OBJECT_NODE
* ObjectNode
;
346 AML_DATA_NODE
* DataNode
;
347 CHAR8
* AmlNameString
;
348 UINT32 AmlNameStringSize
;
350 if ((NameString
== NULL
) ||
352 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
354 return EFI_INVALID_PARAMETER
;
359 AmlNameString
= NULL
;
361 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
362 if (EFI_ERROR (Status
)) {
367 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
368 if (EFI_ERROR (Status
)) {
373 Status
= AmlCreateObjectNode (
374 AmlGetByteEncodingByOpCode (AML_NAME_OP
, 0),
378 if (EFI_ERROR (Status
)) {
383 Status
= AmlCreateDataNode (
384 EAmlNodeDataTypeNameString
,
385 (UINT8
*)AmlNameString
,
389 if (EFI_ERROR (Status
)) {
394 Status
= AmlSetFixedArgument (
397 (AML_NODE_HEADER
*)DataNode
399 if (EFI_ERROR (Status
)) {
401 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
405 Status
= AmlSetFixedArgument (
408 (AML_NODE_HEADER
*)Object
410 if (EFI_ERROR (Status
)) {
420 if (EFI_ERROR (Status
)) {
425 // Free AmlNameString before returning as it is copied
426 // in the call to AmlCreateDataNode().
430 if (ObjectNode
!= NULL
) {
431 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
435 if (AmlNameString
!= NULL
) {
436 FreePool (AmlNameString
);
442 /** AML code generation for a Name object node, containing a String.
444 AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
445 equivalent of the following ASL code:
446 Name(_HID, "HID0000")
448 @param [in] NameString The new variable name.
449 Must be a NULL-terminated ASL NameString
450 e.g.: "DEV0", "DV15.DEV0", etc.
451 The input string is copied.
452 @param [in] String NULL terminated String to associate to the
454 @param [in] ParentNode If provided, set ParentNode as the parent
456 @param [out] NewObjectNode If success, contains the created node.
458 @retval EFI_SUCCESS Success.
459 @retval EFI_INVALID_PARAMETER Invalid parameter.
460 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
464 AmlCodeGenNameString (
465 IN CONST CHAR8
* NameString
,
467 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
468 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
472 AML_OBJECT_NODE
* ObjectNode
;
474 if ((NameString
== NULL
) ||
476 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
478 return EFI_INVALID_PARAMETER
;
481 Status
= AmlCodeGenString (String
, &ObjectNode
);
482 if (EFI_ERROR (Status
)) {
487 Status
= AmlCodeGenName (
493 if (EFI_ERROR (Status
)) {
495 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
501 /** AML code generation for a Name object node, containing an Integer.
503 AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
504 equivalent of the following ASL code:
507 @param [in] NameString The new variable name.
508 Must be a NULL-terminated ASL NameString
509 e.g.: "DEV0", "DV15.DEV0", etc.
510 The input string is copied.
511 @param [in] Integer Integer to associate to the NameString.
512 @param [in] ParentNode If provided, set ParentNode as the parent
514 @param [out] NewObjectNode If success, contains the created node.
516 @retval EFI_SUCCESS Success.
517 @retval EFI_INVALID_PARAMETER Invalid parameter.
518 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
522 AmlCodeGenNameInteger (
523 IN CONST CHAR8
* NameString
,
525 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
526 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
530 AML_OBJECT_NODE
* ObjectNode
;
532 if ((NameString
== NULL
) ||
533 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
535 return EFI_INVALID_PARAMETER
;
538 Status
= AmlCodeGenInteger (Integer
, &ObjectNode
);
539 if (EFI_ERROR (Status
)) {
544 Status
= AmlCodeGenName (
550 if (EFI_ERROR (Status
)) {
552 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
558 /** AML code generation for a Device object node.
560 AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
561 equivalent of the following ASL code:
564 @param [in] NameString The new Device's name.
565 Must be a NULL-terminated ASL NameString
566 e.g.: "DEV0", "DV15.DEV0", etc.
567 The input string is copied.
568 @param [in] ParentNode If provided, set ParentNode as the parent
570 @param [out] NewObjectNode If success, contains the created node.
572 @retval EFI_SUCCESS Success.
573 @retval EFI_INVALID_PARAMETER Invalid parameter.
574 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
579 IN CONST CHAR8
* NameString
,
580 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
581 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
585 AML_OBJECT_NODE
* ObjectNode
;
586 AML_DATA_NODE
* DataNode
;
587 CHAR8
* AmlNameString
;
588 UINT32 AmlNameStringSize
;
590 if ((NameString
== NULL
) ||
591 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
593 return EFI_INVALID_PARAMETER
;
598 AmlNameString
= NULL
;
600 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
601 if (EFI_ERROR (Status
)) {
606 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
607 if (EFI_ERROR (Status
)) {
612 Status
= AmlCreateObjectNode (
613 AmlGetByteEncodingByOpCode (AML_EXT_OP
, AML_EXT_DEVICE_OP
),
614 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
617 if (EFI_ERROR (Status
)) {
622 Status
= AmlCreateDataNode (
623 EAmlNodeDataTypeNameString
,
624 (UINT8
*)AmlNameString
,
628 if (EFI_ERROR (Status
)) {
633 Status
= AmlSetFixedArgument (
636 (AML_NODE_HEADER
*)DataNode
638 if (EFI_ERROR (Status
)) {
640 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
649 if (EFI_ERROR (Status
)) {
654 // Free AmlNameString before returning as it is copied
655 // in the call to AmlCreateDataNode().
659 if (ObjectNode
!= NULL
) {
660 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
664 if (AmlNameString
!= NULL
) {
665 FreePool (AmlNameString
);
671 /** AML code generation for a Scope object node.
673 AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
674 equivalent of the following ASL code:
677 @param [in] NameString The new Scope's name.
678 Must be a NULL-terminated ASL NameString
679 e.g.: "DEV0", "DV15.DEV0", etc.
680 The input string is copied.
681 @param [in] ParentNode If provided, set ParentNode as the parent
683 @param [out] NewObjectNode If success, contains the created node.
685 @retval EFI_SUCCESS Success.
686 @retval EFI_INVALID_PARAMETER Invalid parameter.
687 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
692 IN CONST CHAR8
* NameString
,
693 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
694 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
698 AML_OBJECT_NODE
* ObjectNode
;
699 AML_DATA_NODE
* DataNode
;
700 CHAR8
* AmlNameString
;
701 UINT32 AmlNameStringSize
;
703 if ((NameString
== NULL
) ||
704 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
706 return EFI_INVALID_PARAMETER
;
711 AmlNameString
= NULL
;
713 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
714 if (EFI_ERROR (Status
)) {
719 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
720 if (EFI_ERROR (Status
)) {
725 Status
= AmlCreateObjectNode (
726 AmlGetByteEncodingByOpCode (AML_SCOPE_OP
, 0),
727 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
730 if (EFI_ERROR (Status
)) {
735 Status
= AmlCreateDataNode (
736 EAmlNodeDataTypeNameString
,
737 (UINT8
*)AmlNameString
,
741 if (EFI_ERROR (Status
)) {
746 Status
= AmlSetFixedArgument (
749 (AML_NODE_HEADER
*)DataNode
751 if (EFI_ERROR (Status
)) {
753 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
762 if (EFI_ERROR (Status
)) {
767 // Free AmlNameString before returning as it is copied
768 // in the call to AmlCreateDataNode().
772 if (ObjectNode
!= NULL
) {
773 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
777 if (AmlNameString
!= NULL
) {
778 FreePool (AmlNameString
);