]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / Tree / AmlClone.c
1 /** @file
2 AML Clone.
3
4 Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <AmlNodeDefines.h>
10
11 #include <AmlCoreInterface.h>
12 #include <Tree/AmlNode.h>
13 #include <Tree/AmlTree.h>
14
15 /** Clone a node.
16
17 This function does not clone the children nodes.
18 The cloned node returned is not attached to any tree.
19
20 @param [in] Node Pointer to a node.
21 @param [out] ClonedNode Pointer holding the cloned node.
22
23 @retval EFI_SUCCESS The function completed successfully.
24 @retval EFI_INVALID_PARAMETER Invalid parameter.
25 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
26 **/
27 EFI_STATUS
28 EFIAPI
29 AmlCloneNode (
30 IN AML_NODE_HEADER *Node,
31 OUT AML_NODE_HEADER **ClonedNode
32 )
33 {
34 EFI_STATUS Status;
35
36 AML_OBJECT_NODE *ObjectNode;
37 AML_DATA_NODE *DataNode;
38 AML_ROOT_NODE *RootNode;
39
40 if (!IS_AML_NODE_VALID (Node) ||
41 (ClonedNode == NULL))
42 {
43 ASSERT (0);
44 return EFI_INVALID_PARAMETER;
45 }
46
47 if (IS_AML_DATA_NODE (Node)) {
48 DataNode = (AML_DATA_NODE *)Node;
49 Status = AmlCreateDataNode (
50 DataNode->DataType,
51 DataNode->Buffer,
52 DataNode->Size,
53 (AML_DATA_NODE **)ClonedNode
54 );
55 if (EFI_ERROR (Status)) {
56 ASSERT (0);
57 }
58 } else if (IS_AML_OBJECT_NODE (Node)) {
59 ObjectNode = (AML_OBJECT_NODE *)Node;
60
61 Status = AmlCreateObjectNode (
62 ObjectNode->AmlByteEncoding,
63 ObjectNode->PkgLen,
64 (AML_OBJECT_NODE **)ClonedNode
65 );
66 if (EFI_ERROR (Status)) {
67 ASSERT (0);
68 }
69 } else if (IS_AML_ROOT_NODE (Node)) {
70 RootNode = (AML_ROOT_NODE *)Node;
71
72 Status = AmlCreateRootNode (
73 RootNode->SdtHeader,
74 (AML_ROOT_NODE **)ClonedNode
75 );
76 if (EFI_ERROR (Status)) {
77 ASSERT (0);
78 }
79 } else {
80 ASSERT (0);
81 return EFI_INVALID_PARAMETER;
82 }
83
84 return Status;
85 }
86
87 /** Clone a node and its children (clone a tree branch).
88
89 The cloned branch returned is not attached to any tree.
90
91 @param [in] Node Pointer to a node.
92 Node is the head of the branch to clone.
93 @param [out] ClonedNode Pointer holding the head of the created cloned
94 branch.
95
96 @retval EFI_SUCCESS The function completed successfully.
97 @retval EFI_INVALID_PARAMETER Invalid parameter.
98 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
99 **/
100 EFI_STATUS
101 EFIAPI
102 AmlCloneTree (
103 IN AML_NODE_HEADER *Node,
104 OUT AML_NODE_HEADER **ClonedNode
105 )
106 {
107 EFI_STATUS Status;
108
109 AML_NODE_HEADER *HeadNode;
110 AML_NODE_HEADER *ClonedChildNode;
111 AML_NODE_HEADER *FixedArgNode;
112
113 EAML_PARSE_INDEX Index;
114 EAML_PARSE_INDEX MaxIndex;
115
116 LIST_ENTRY *StartLink;
117 LIST_ENTRY *CurrentLink;
118
119 if (!IS_AML_NODE_VALID (Node) ||
120 (ClonedNode == NULL))
121 {
122 ASSERT (0);
123 return EFI_INVALID_PARAMETER;
124 }
125
126 Status = AmlCloneNode (Node, &HeadNode);
127 if (EFI_ERROR (Status)) {
128 ASSERT (0);
129 return Status;
130 }
131
132 // Clone the fixed arguments and bind them to their parent.
133 MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
134 (AML_OBJECT_NODE *)Node
135 );
136 for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
137 FixedArgNode = AmlGetFixedArgument ((AML_OBJECT_NODE *)Node, Index);
138 if (FixedArgNode == NULL) {
139 Status = EFI_INVALID_PARAMETER;
140 ASSERT (0);
141 goto error_handler;
142 }
143
144 // Clone child.
145 Status = AmlCloneTree (
146 FixedArgNode,
147 &ClonedChildNode
148 );
149 if (EFI_ERROR (Status)) {
150 ASSERT (0);
151 goto error_handler;
152 }
153
154 // Bind child.
155 Status = AmlSetFixedArgument (
156 (AML_OBJECT_NODE *)HeadNode,
157 Index,
158 ClonedChildNode
159 );
160 if (EFI_ERROR (Status)) {
161 AmlDeleteTree (ClonedChildNode);
162 ASSERT (0);
163 goto error_handler;
164 }
165 } // for
166
167 // Clone the variable arguments and bind them to their parent.
168 StartLink = AmlNodeGetVariableArgList (Node);
169 if (StartLink != NULL) {
170 CurrentLink = StartLink->ForwardLink;
171 while (CurrentLink != StartLink) {
172 // Clone child.
173 Status = AmlCloneTree ((AML_NODE_HEADER *)CurrentLink, &ClonedChildNode);
174 if (EFI_ERROR (Status)) {
175 ASSERT (0);
176 goto error_handler;
177 }
178
179 // Bind child.
180 Status = AmlVarListAddTailInternal (
181 HeadNode,
182 ClonedChildNode
183 );
184 if (EFI_ERROR (Status)) {
185 AmlDeleteTree (ClonedChildNode);
186 ASSERT (0);
187 goto error_handler;
188 }
189
190 CurrentLink = CurrentLink->ForwardLink;
191 } // while
192 }
193
194 *ClonedNode = HeadNode;
195 return Status;
196
197 error_handler:
198 *ClonedNode = NULL;
199
200 if (HeadNode != NULL) {
201 AmlDeleteTree (HeadNode);
202 }
203
204 return Status;
205 }