4 Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <AmlNodeDefines.h>
11 #include <AmlCoreInterface.h>
12 #include <Stream/AmlStream.h>
13 #include <Tree/AmlNode.h>
14 #include <Tree/AmlTree.h>
15 #include <Utils/AmlUtility.h>
17 /** Callback function to copy the AML bytecodes contained in a node
18 to the Stream stored in the Context.
19 The SDT header data contained in the root node is not serialized
22 @param [in] Node Pointer to the node to copy the AML bytecodes
24 @param [in, out] Context Contains a forward Stream to write to.
26 @param [in, out] Status At entry, contains the status returned by the
27 last call to this exact function during the
29 As exit, contains the returned status of the
30 call to this function.
31 Optional, can be NULL.
33 @retval TRUE if the enumeration can continue or has finished without
35 @retval FALSE if the enumeration needs to stopped or has stopped.
40 AmlSerializeNodeCallback (
41 IN AML_NODE_HEADER
* Node
,
42 IN OUT VOID
* Context OPTIONAL
,
43 IN OUT EFI_STATUS
* Status OPTIONAL
48 CONST AML_DATA_NODE
* DataNode
;
49 CONST AML_OBJECT_NODE
* ObjectNode
;
52 // Bytes needed to store OpCode[1] + SubOpcode[1] + MaxPkgLen[4] = 6 bytes.
53 UINT8 ObjectNodeInfoArray
[6];
57 CONST AML_OBJECT_NODE
* ParentNode
;
58 EAML_PARSE_INDEX IndexPtr
;
60 if (!IS_AML_NODE_VALID (Node
) ||
63 Status1
= EFI_INVALID_PARAMETER
;
68 // Ignore the second fixed argument of method invocation nodes
69 // as the information stored there (the argument count) is not in the
70 // ACPI specification.
71 ParentNode
= (CONST AML_OBJECT_NODE
*)AmlGetParent ((AML_NODE_HEADER
*)Node
);
72 if (IS_AML_OBJECT_NODE (ParentNode
) &&
73 AmlNodeCompareOpCode (ParentNode
, AML_METHOD_INVOC_OP
, 0) &&
74 AmlIsNodeFixedArgument (Node
, &IndexPtr
)) {
75 if (IndexPtr
== EAmlParseIndexTerm1
) {
77 *Status
= EFI_SUCCESS
;
83 Status1
= EFI_SUCCESS
;
85 FStream
= (AML_STREAM
*)Context
;
87 if (IS_AML_DATA_NODE (Node
)) {
88 // Copy the content of the Buffer for a DataNode.
89 DataNode
= (AML_DATA_NODE
*)Node
;
90 Status1
= AmlStreamWrite (
95 if (EFI_ERROR (Status1
)) {
101 } else if (IS_AML_OBJECT_NODE (Node
) &&
102 !AmlNodeHasAttribute (
103 (CONST AML_OBJECT_NODE
*)Node
,
104 AML_IS_PSEUDO_OPCODE
)) {
105 // Ignore pseudo-opcodes as they are not part of the
106 // ACPI specification.
108 ObjectNode
= (AML_OBJECT_NODE
*)Node
;
111 // Copy the opcode(s).
112 ObjectNodeInfoArray
[Index
++] = ObjectNode
->AmlByteEncoding
->OpCode
;
113 if (ObjectNode
->AmlByteEncoding
->OpCode
== AML_EXT_OP
) {
114 ObjectNodeInfoArray
[Index
++] = ObjectNode
->AmlByteEncoding
->SubOpCode
;
118 if (AmlNodeHasAttribute (ObjectNode
, AML_HAS_PKG_LENGTH
)) {
119 Index
+= AmlSetPkgLength (
121 &ObjectNodeInfoArray
[Index
]
125 Status1
= AmlStreamWrite (
130 if (EFI_ERROR (Status1
)) {
132 ContinueEnum
= FALSE
;
135 } // IS_AML_OBJECT_NODE (Node)
138 if (Status
!= NULL
) {
144 /** Serialize a tree to create an ACPI DSDT/SSDT table.
147 - the content of BufferSize is >= to the size needed to serialize the
149 - Buffer is not NULL;
150 first serialize the ACPI DSDT/SSDT header from the root node,
151 then serialize the AML blob from the rest of the tree.
153 The content of BufferSize is always updated to the size needed to
154 serialize the definition block.
156 @param [in] RootNode Pointer to a root node.
157 @param [in] Buffer Buffer to write the DSDT/SSDT table to.
158 If Buffer is NULL, the size needed to
159 serialize the DSDT/SSDT table is returned
161 @param [in, out] BufferSize Pointer holding the size of the Buffer.
162 Its content is always updated to the size
163 needed to serialize the DSDT/SSDT table.
165 @retval EFI_SUCCESS The function completed successfully.
166 @retval EFI_INVALID_PARAMETER Invalid parameter.
167 @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
172 IN AML_ROOT_NODE
* RootNode
,
173 IN UINT8
* Buffer OPTIONAL
,
174 IN OUT UINT32
* BufferSize
181 if (!IS_AML_ROOT_NODE (RootNode
) ||
182 (BufferSize
== NULL
)) {
184 return EFI_INVALID_PARAMETER
;
187 // Compute the total size of the AML blob.
188 Status
= AmlComputeSize (
189 (CONST AML_NODE_HEADER
*)RootNode
,
192 if (EFI_ERROR (Status
)) {
197 // Add the size of the ACPI header.
198 TableSize
+= (UINT32
)sizeof (EFI_ACPI_DESCRIPTION_HEADER
);
200 // Check the size against the SDT header.
201 // The Length field in the SDT Header is updated if the tree has
203 if (TableSize
!= RootNode
->SdtHeader
->Length
) {
205 return EFI_INVALID_PARAMETER
;
208 // Buffer is not big enough, or NULL.
209 if ((TableSize
< *BufferSize
) || (Buffer
== NULL
)) {
210 *BufferSize
= TableSize
;
214 // Initialize the stream to the TableSize that is needed.
215 Status
= AmlStreamInit (
219 EAmlStreamDirectionForward
221 if (EFI_ERROR (Status
)) {
226 // Serialize the header.
227 Status
= AmlStreamWrite (
229 (UINT8
*)RootNode
->SdtHeader
,
230 sizeof (EFI_ACPI_DESCRIPTION_HEADER
)
232 if (EFI_ERROR (Status
)) {
237 Status
= EFI_SUCCESS
;
239 (AML_NODE_HEADER
*)RootNode
,
240 AmlSerializeNodeCallback
,
244 if (EFI_ERROR (Status
)) {
249 // Update the checksum.
250 return AcpiPlatformChecksum ((EFI_ACPI_DESCRIPTION_HEADER
*)Buffer
);
253 /** Serialize an AML definition block.
255 This functions allocates memory with the "AllocateZeroPool ()"
256 function. This memory is used to serialize the AML tree and is
257 returned in the Table.
259 @param [in] RootNode Root node of the tree.
260 @param [out] Table On return, hold the serialized
263 @retval EFI_SUCCESS The function completed successfully.
264 @retval EFI_INVALID_PARAMETER Invalid parameter.
265 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
269 AmlSerializeDefinitionBlock (
270 IN AML_ROOT_NODE
* RootNode
,
271 OUT EFI_ACPI_DESCRIPTION_HEADER
** Table
278 if (!IS_AML_ROOT_NODE (RootNode
) ||
281 return EFI_INVALID_PARAMETER
;
288 // Get the size of the SSDT table.
289 Status
= AmlSerializeTree (
294 if (EFI_ERROR (Status
)) {
299 TableBuffer
= (UINT8
*)AllocateZeroPool (TableSize
);
300 if (TableBuffer
== NULL
) {
303 "ERROR: Failed to allocate memory for Table Buffer."
306 return EFI_OUT_OF_RESOURCES
;
309 // Serialize the tree to a SSDT table.
310 Status
= AmlSerializeTree (
315 if (EFI_ERROR (Status
)) {
316 FreePool (TableBuffer
);
319 // Save the allocated Table buffer in the table list
320 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)TableBuffer
;