4 Copyright (c) 2020, 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 success, contains the created object node.
27 @retval EFI_SUCCESS The function completed successfully.
28 @retval EFI_INVALID_PARAMETER Invalid parameter.
34 IN AML_OBJECT_NODE
* Node
,
35 IN AML_NODE_HEADER
* ParentNode
,
36 OUT AML_OBJECT_NODE
** NewObjectNode
41 if (NewObjectNode
!= NULL
) {
42 *NewObjectNode
= Node
;
45 // Add RdNode as the last element.
46 if (ParentNode
!= NULL
) {
47 Status
= AmlVarListAddTail (ParentNode
, (AML_NODE_HEADER
*)Node
);
48 if (EFI_ERROR (Status
)) {
57 /** AML code generation for DefinitionBlock.
59 Create a Root Node handle.
60 It is the caller's responsibility to free the allocated memory
61 with the AmlDeleteTree function.
63 AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
64 equivalent to the following ASL code:
65 DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
66 OemID, TableID, OEMRevision) {}
67 with the ComplianceRevision set to 2 and the AMLFileName is ignored.
69 @param[in] TableSignature 4-character ACPI signature.
70 Must be 'DSDT' or 'SSDT'.
71 @param[in] OemId 6-character string OEM identifier.
72 @param[in] OemTableId 8-character string OEM table identifier.
73 @param[in] OemRevision OEM revision number.
74 @param[out] NewRootNode Pointer to the root node representing a
77 @retval EFI_SUCCESS Success.
78 @retval EFI_INVALID_PARAMETER Invalid parameter.
79 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
83 AmlCodeGenDefinitionBlock (
84 IN CONST CHAR8
* TableSignature
,
85 IN CONST CHAR8
* OemId
,
86 IN CONST CHAR8
* OemTableId
,
87 IN UINT32 OemRevision
,
88 OUT AML_ROOT_NODE
** NewRootNode
92 EFI_ACPI_DESCRIPTION_HEADER AcpiHeader
;
94 if ((TableSignature
== NULL
) ||
96 (OemTableId
== NULL
) ||
97 (NewRootNode
== NULL
)) {
99 return EFI_INVALID_PARAMETER
;
102 CopyMem (&AcpiHeader
.Signature
, TableSignature
, 4);
103 AcpiHeader
.Length
= sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
104 AcpiHeader
.Revision
= 2;
105 CopyMem (&AcpiHeader
.OemId
, OemId
, 6);
106 CopyMem (&AcpiHeader
.OemTableId
, OemTableId
, 8);
107 AcpiHeader
.OemRevision
= OemRevision
;
108 AcpiHeader
.CreatorId
= TABLE_GENERATOR_CREATOR_ID_ARM
;
109 AcpiHeader
.CreatorRevision
= CREATE_REVISION (1, 0);
111 Status
= AmlCreateRootNode (&AcpiHeader
, NewRootNode
);
112 ASSERT_EFI_ERROR (Status
);
117 /** AML code generation for a String object node.
119 @param [in] String Pointer to a NULL terminated string.
120 @param [out] NewObjectNode If success, contains the created
123 @retval EFI_SUCCESS Success.
124 @retval EFI_INVALID_PARAMETER Invalid parameter.
125 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
132 OUT AML_OBJECT_NODE
** NewObjectNode
136 AML_OBJECT_NODE
* ObjectNode
;
137 AML_DATA_NODE
* DataNode
;
139 if ((String
== NULL
) ||
140 (NewObjectNode
== NULL
)) {
142 return EFI_INVALID_PARAMETER
;
148 Status
= AmlCreateObjectNode (
149 AmlGetByteEncodingByOpCode (AML_STRING_PREFIX
, 0),
153 if (EFI_ERROR (Status
)) {
158 Status
= AmlCreateDataNode (
159 EAmlNodeDataTypeString
,
161 (UINT32
)AsciiStrLen (String
) + 1,
164 if (EFI_ERROR (Status
)) {
169 Status
= AmlSetFixedArgument (
172 (AML_NODE_HEADER
*)DataNode
174 if (EFI_ERROR (Status
)) {
176 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
180 *NewObjectNode
= ObjectNode
;
184 if (ObjectNode
!= NULL
) {
185 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
191 /** AML code generation for an Integer object node.
193 @param [in] Integer Integer of the Integer object node.
194 @param [out] NewObjectNode If success, contains the created
197 @retval EFI_SUCCESS Success.
198 @retval EFI_INVALID_PARAMETER Invalid parameter.
199 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
206 OUT AML_OBJECT_NODE
** NewObjectNode
212 if (NewObjectNode
== NULL
) {
214 return EFI_INVALID_PARAMETER
;
217 // Create an object node containing Zero.
218 Status
= AmlCreateObjectNode (
219 AmlGetByteEncodingByOpCode (AML_ZERO_OP
, 0),
223 if (EFI_ERROR (Status
)) {
228 // Update the object node with integer value.
229 Status
= AmlNodeSetIntegerValue (*NewObjectNode
, Integer
, &ValueWidthDiff
);
230 if (EFI_ERROR (Status
)) {
232 AmlDeleteTree ((AML_NODE_HEADER
*)*NewObjectNode
);
238 /** AML code generation for a Name object node.
240 @param [in] NameString The new variable name.
241 Must be a NULL-terminated ASL NameString
242 e.g.: "DEV0", "DV15.DEV0", etc.
243 This input string is copied.
244 @param [in] Object Object associated to the NameString.
245 @param [in] ParentNode If provided, set ParentNode as the parent
247 @param [out] NewObjectNode If success, contains the created node.
249 @retval EFI_SUCCESS Success.
250 @retval EFI_INVALID_PARAMETER Invalid parameter.
251 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
257 IN CONST CHAR8
* NameString
,
258 IN AML_OBJECT_NODE
* Object
,
259 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
260 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
264 AML_OBJECT_NODE
* ObjectNode
;
265 AML_DATA_NODE
* DataNode
;
266 CHAR8
* AmlNameString
;
267 UINT32 AmlNameStringSize
;
269 if ((NameString
== NULL
) ||
271 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
273 return EFI_INVALID_PARAMETER
;
278 AmlNameString
= NULL
;
280 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
281 if (EFI_ERROR (Status
)) {
286 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
287 if (EFI_ERROR (Status
)) {
292 Status
= AmlCreateObjectNode (
293 AmlGetByteEncodingByOpCode (AML_NAME_OP
, 0),
297 if (EFI_ERROR (Status
)) {
302 Status
= AmlCreateDataNode (
303 EAmlNodeDataTypeNameString
,
304 (UINT8
*)AmlNameString
,
308 if (EFI_ERROR (Status
)) {
313 Status
= AmlSetFixedArgument (
316 (AML_NODE_HEADER
*)DataNode
318 if (EFI_ERROR (Status
)) {
320 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
324 Status
= AmlSetFixedArgument (
327 (AML_NODE_HEADER
*)Object
329 if (EFI_ERROR (Status
)) {
339 if (EFI_ERROR (Status
)) {
344 // Free AmlNameString before returning as it is copied
345 // in the call to AmlCreateDataNode().
349 if (ObjectNode
!= NULL
) {
350 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
354 if (AmlNameString
!= NULL
) {
355 FreePool (AmlNameString
);
361 /** AML code generation for a Name object node, containing a String.
363 AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
364 equivalent of the following ASL code:
365 Name(_HID, "HID0000")
367 @param [in] NameString The new variable name.
368 Must be a NULL-terminated ASL NameString
369 e.g.: "DEV0", "DV15.DEV0", etc.
370 The input string is copied.
371 @param [in] String NULL terminated String to associate to the
373 @param [in] ParentNode If provided, set ParentNode as the parent
375 @param [out] NewObjectNode If success, contains the created node.
377 @retval EFI_SUCCESS Success.
378 @retval EFI_INVALID_PARAMETER Invalid parameter.
379 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
383 AmlCodeGenNameString (
384 IN CONST CHAR8
* NameString
,
386 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
387 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
391 AML_OBJECT_NODE
* ObjectNode
;
393 if ((NameString
== NULL
) ||
395 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
397 return EFI_INVALID_PARAMETER
;
400 Status
= AmlCodeGenString (String
, &ObjectNode
);
401 if (EFI_ERROR (Status
)) {
406 Status
= AmlCodeGenName (
412 if (EFI_ERROR (Status
)) {
414 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
420 /** AML code generation for a Name object node, containing an Integer.
422 AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
423 equivalent of the following ASL code:
426 @param [in] NameString The new variable name.
427 Must be a NULL-terminated ASL NameString
428 e.g.: "DEV0", "DV15.DEV0", etc.
429 The input string is copied.
430 @param [in] Integer Integer to associate to the NameString.
431 @param [in] ParentNode If provided, set ParentNode as the parent
433 @param [out] NewObjectNode If success, contains the created node.
435 @retval EFI_SUCCESS Success.
436 @retval EFI_INVALID_PARAMETER Invalid parameter.
437 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
441 AmlCodeGenNameInteger (
442 IN CONST CHAR8
* NameString
,
444 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
445 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
449 AML_OBJECT_NODE
* ObjectNode
;
451 if ((NameString
== NULL
) ||
452 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
454 return EFI_INVALID_PARAMETER
;
457 Status
= AmlCodeGenInteger (Integer
, &ObjectNode
);
458 if (EFI_ERROR (Status
)) {
463 Status
= AmlCodeGenName (
469 if (EFI_ERROR (Status
)) {
471 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
477 /** AML code generation for a Device object node.
479 AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
480 equivalent of the following ASL code:
483 @param [in] NameString The new Device's name.
484 Must be a NULL-terminated ASL NameString
485 e.g.: "DEV0", "DV15.DEV0", etc.
486 The input string is copied.
487 @param [in] ParentNode If provided, set ParentNode as the parent
489 @param [out] NewObjectNode If success, contains the created node.
491 @retval EFI_SUCCESS Success.
492 @retval EFI_INVALID_PARAMETER Invalid parameter.
493 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
498 IN CONST CHAR8
* NameString
,
499 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
500 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
504 AML_OBJECT_NODE
* ObjectNode
;
505 AML_DATA_NODE
* DataNode
;
506 CHAR8
* AmlNameString
;
507 UINT32 AmlNameStringSize
;
509 if ((NameString
== NULL
) ||
510 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
512 return EFI_INVALID_PARAMETER
;
517 AmlNameString
= NULL
;
519 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
520 if (EFI_ERROR (Status
)) {
525 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
526 if (EFI_ERROR (Status
)) {
531 Status
= AmlCreateObjectNode (
532 AmlGetByteEncodingByOpCode (AML_EXT_OP
, AML_EXT_DEVICE_OP
),
533 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
536 if (EFI_ERROR (Status
)) {
541 Status
= AmlCreateDataNode (
542 EAmlNodeDataTypeNameString
,
543 (UINT8
*)AmlNameString
,
547 if (EFI_ERROR (Status
)) {
552 Status
= AmlSetFixedArgument (
555 (AML_NODE_HEADER
*)DataNode
557 if (EFI_ERROR (Status
)) {
559 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
568 if (EFI_ERROR (Status
)) {
573 // Free AmlNameString before returning as it is copied
574 // in the call to AmlCreateDataNode().
578 if (ObjectNode
!= NULL
) {
579 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
583 if (AmlNameString
!= NULL
) {
584 FreePool (AmlNameString
);
590 /** AML code generation for a Scope object node.
592 AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
593 equivalent of the following ASL code:
596 @param [in] NameString The new Scope's name.
597 Must be a NULL-terminated ASL NameString
598 e.g.: "DEV0", "DV15.DEV0", etc.
599 The input string is copied.
600 @param [in] ParentNode If provided, set ParentNode as the parent
602 @param [out] NewObjectNode If success, contains the created node.
604 @retval EFI_SUCCESS Success.
605 @retval EFI_INVALID_PARAMETER Invalid parameter.
606 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
611 IN CONST CHAR8
* NameString
,
612 IN AML_NODE_HEADER
* ParentNode
, OPTIONAL
613 OUT AML_OBJECT_NODE
** NewObjectNode OPTIONAL
617 AML_OBJECT_NODE
* ObjectNode
;
618 AML_DATA_NODE
* DataNode
;
619 CHAR8
* AmlNameString
;
620 UINT32 AmlNameStringSize
;
622 if ((NameString
== NULL
) ||
623 ((ParentNode
== NULL
) && (NewObjectNode
== NULL
))) {
625 return EFI_INVALID_PARAMETER
;
630 AmlNameString
= NULL
;
632 Status
= ConvertAslNameToAmlName (NameString
, &AmlNameString
);
633 if (EFI_ERROR (Status
)) {
638 Status
= AmlGetNameStringSize (AmlNameString
, &AmlNameStringSize
);
639 if (EFI_ERROR (Status
)) {
644 Status
= AmlCreateObjectNode (
645 AmlGetByteEncodingByOpCode (AML_SCOPE_OP
, 0),
646 AmlNameStringSize
+ AmlComputePkgLengthWidth (AmlNameStringSize
),
649 if (EFI_ERROR (Status
)) {
654 Status
= AmlCreateDataNode (
655 EAmlNodeDataTypeNameString
,
656 (UINT8
*)AmlNameString
,
660 if (EFI_ERROR (Status
)) {
665 Status
= AmlSetFixedArgument (
668 (AML_NODE_HEADER
*)DataNode
670 if (EFI_ERROR (Status
)) {
672 AmlDeleteTree ((AML_NODE_HEADER
*)DataNode
);
681 if (EFI_ERROR (Status
)) {
686 // Free AmlNameString before returning as it is copied
687 // in the call to AmlCreateDataNode().
691 if (ObjectNode
!= NULL
) {
692 AmlDeleteTree ((AML_NODE_HEADER
*)ObjectNode
);
696 if (AmlNameString
!= NULL
) {
697 FreePool (AmlNameString
);