]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c
7aafa957a8c402fad37caa2beb0a3d5fd96fd344
[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 ASSERT (0);
43 return EFI_INVALID_PARAMETER;
44 }
45
46 if (IS_AML_DATA_NODE (Node)) {
47 DataNode = (AML_DATA_NODE*)Node;
48 Status = AmlCreateDataNode (
49 DataNode->DataType,
50 DataNode->Buffer,
51 DataNode->Size,
52 (AML_DATA_NODE**)ClonedNode
53 );
54 if (EFI_ERROR (Status)) {
55 ASSERT (0);
56 }
57 } else if (IS_AML_OBJECT_NODE (Node)) {
58 ObjectNode = (AML_OBJECT_NODE*)Node;
59
60 Status = AmlCreateObjectNode (
61 ObjectNode->AmlByteEncoding,
62 ObjectNode->PkgLen,
63 (AML_OBJECT_NODE**)ClonedNode
64 );
65 if (EFI_ERROR (Status)) {
66 ASSERT (0);
67 }
68 } else if (IS_AML_ROOT_NODE (Node)) {
69 RootNode = (AML_ROOT_NODE*)Node;
70
71 Status = AmlCreateRootNode (
72 RootNode->SdtHeader,
73 (AML_ROOT_NODE**)ClonedNode
74 );
75 if (EFI_ERROR (Status)) {
76 ASSERT (0);
77 }
78 } else {
79 ASSERT (0);
80 return EFI_INVALID_PARAMETER;
81 }
82
83 return Status;
84 }
85
86 /** Clone a node and its children (clone a tree branch).
87
88 The cloned branch returned is not attached to any tree.
89
90 @param [in] Node Pointer to a node.
91 Node is the head of the branch to clone.
92 @param [out] ClonedNode Pointer holding the head of the created cloned
93 branch.
94
95 @retval EFI_SUCCESS The function completed successfully.
96 @retval EFI_INVALID_PARAMETER Invalid parameter.
97 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
98 **/
99 EFI_STATUS
100 EFIAPI
101 AmlCloneTree (
102 IN AML_NODE_HEADER * Node,
103 OUT AML_NODE_HEADER ** ClonedNode
104 )
105 {
106 EFI_STATUS Status;
107
108 AML_NODE_HEADER * HeadNode;
109 AML_NODE_HEADER * ClonedChildNode;
110 AML_NODE_HEADER * FixedArgNode;
111
112 EAML_PARSE_INDEX Index;
113 EAML_PARSE_INDEX MaxIndex;
114
115 LIST_ENTRY * StartLink;
116 LIST_ENTRY * CurrentLink;
117
118 if (!IS_AML_NODE_VALID (Node) ||
119 (ClonedNode == NULL)) {
120 ASSERT (0);
121 return EFI_INVALID_PARAMETER;
122 }
123
124 Status = AmlCloneNode (Node, &HeadNode);
125 if (EFI_ERROR (Status)) {
126 ASSERT (0);
127 return Status;
128 }
129
130 // Clone the fixed arguments and bind them to their parent.
131 MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
132 (AML_OBJECT_NODE*)Node
133 );
134 for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
135 FixedArgNode = AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index);
136 if (FixedArgNode == NULL) {
137 Status = EFI_INVALID_PARAMETER;
138 ASSERT (0);
139 goto error_handler;
140 }
141
142 // Clone child.
143 Status = AmlCloneTree (
144 FixedArgNode,
145 &ClonedChildNode
146 );
147 if (EFI_ERROR (Status)) {
148 ASSERT (0);
149 goto error_handler;
150 }
151
152 // Bind child.
153 Status = AmlSetFixedArgument (
154 (AML_OBJECT_NODE*)HeadNode,
155 Index,
156 ClonedChildNode
157 );
158 if (EFI_ERROR (Status)) {
159 AmlDeleteTree (ClonedChildNode);
160 ASSERT (0);
161 goto error_handler;
162 }
163 } // for
164
165 // Clone the variable arguments and bind them to their parent.
166 StartLink = AmlNodeGetVariableArgList (Node);
167 if (StartLink != NULL) {
168 CurrentLink = StartLink->ForwardLink;
169 while (CurrentLink != StartLink) {
170 // Clone child.
171 Status = AmlCloneTree ((AML_NODE_HEADER*)CurrentLink, &ClonedChildNode);
172 if (EFI_ERROR (Status)) {
173 ASSERT (0);
174 goto error_handler;
175 }
176
177 // Bind child.
178 Status = AmlVarListAddTailInternal (
179 HeadNode,
180 ClonedChildNode
181 );
182 if (EFI_ERROR (Status)) {
183 AmlDeleteTree (ClonedChildNode);
184 ASSERT (0);
185 goto error_handler;
186 }
187
188 CurrentLink = CurrentLink->ForwardLink;
189 } // while
190 }
191
192 *ClonedNode = HeadNode;
193 return Status;
194
195 error_handler:
196 *ClonedNode = NULL;
197
198 if (HeadNode != NULL) {
199 AmlDeleteTree (HeadNode);
200 }
201
202 return Status;
203 }