]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / Tree / AmlTreeIterator.c
CommitLineData
e2c1104c
PG
1/** @file\r
2 AML Tree Iterator.\r
3\r
4 Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>\r
5\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7**/\r
8\r
9#include <AmlNodeDefines.h>\r
10#include <Tree/AmlTreeIterator.h>\r
11\r
12#include <AmlCoreInterface.h>\r
13#include <Tree/AmlTreeTraversal.h>\r
14\r
15/** Iterator to traverse the tree.\r
16\r
17 This is an internal structure.\r
18*/\r
19typedef struct AmlTreeInternalIterator {\r
20 /// External iterator structure, containing the external APIs.\r
21 /// Must be the first field.\r
22 AML_TREE_ITERATOR Iterator;\r
23\r
24 // Note: The following members of this structure are opaque to the users\r
25 // of the Tree iterator APIs.\r
26\r
27 /// Pointer to the node on which the iterator has been initialized.\r
731c67e1 28 CONST AML_NODE_HEADER *InitialNode;\r
e2c1104c
PG
29\r
30 /// Pointer to the current node.\r
731c67e1 31 CONST AML_NODE_HEADER *CurrentNode;\r
e2c1104c
PG
32\r
33 /// Iteration mode.\r
34 /// Allow to choose how to traverse the tree/choose which node is next.\r
35 EAML_ITERATOR_MODE Mode;\r
36} AML_TREE_ITERATOR_INTERNAL;\r
37\r
38/** Get the current node of an iterator.\r
39\r
40 @param [in] Iterator Pointer to an iterator.\r
41 @param [out] OutNode Pointer holding the current node.\r
42\r
43 @retval EFI_SUCCESS The function completed successfully.\r
44 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
45**/\r
46STATIC\r
47EFI_STATUS\r
48EFIAPI\r
49AmlIteratorGetNode (\r
731c67e1
MK
50 IN AML_TREE_ITERATOR *Iterator,\r
51 OUT AML_NODE_HEADER **OutNode\r
e2c1104c
PG
52 )\r
53{\r
731c67e1 54 AML_TREE_ITERATOR_INTERNAL *InternalIterator;\r
e2c1104c 55\r
731c67e1 56 InternalIterator = (AML_TREE_ITERATOR_INTERNAL *)Iterator;\r
e2c1104c
PG
57\r
58 // CurrentNode can be NULL, but InitialNode cannot.\r
59 if ((OutNode == NULL) ||\r
60 (InternalIterator == NULL) ||\r
61 (InternalIterator->Mode <= EAmlIteratorUnknown) ||\r
62 (InternalIterator->Mode >= EAmlIteratorModeMax) ||\r
63 !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||\r
64 ((InternalIterator->CurrentNode != NULL) &&\r
731c67e1
MK
65 !IS_AML_NODE_VALID (InternalIterator->CurrentNode)))\r
66 {\r
e2c1104c
PG
67 ASSERT (0);\r
68 return EFI_INVALID_PARAMETER;\r
69 }\r
70\r
731c67e1 71 *OutNode = (AML_NODE_HEADER *)InternalIterator->CurrentNode;\r
e2c1104c
PG
72\r
73 return EFI_SUCCESS;\r
74}\r
75\r
76/** Move the current node of the iterator to the next node,\r
77 according to the iteration mode selected.\r
78\r
79 If NextNode is not NULL, return the next node.\r
80\r
81 @param [in] Iterator Pointer to an iterator.\r
82 @param [out] NextNode If not NULL, updated to the next node.\r
83\r
84 @retval EFI_SUCCESS The function completed successfully.\r
85 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
86**/\r
87STATIC\r
88EFI_STATUS\r
89EFIAPI\r
90AmlIteratorGetNextLinear (\r
731c67e1
MK
91 IN AML_TREE_ITERATOR *Iterator,\r
92 OUT AML_NODE_HEADER **NextNode\r
e2c1104c
PG
93 )\r
94{\r
731c67e1 95 AML_TREE_ITERATOR_INTERNAL *InternalIterator;\r
e2c1104c 96\r
731c67e1 97 InternalIterator = (AML_TREE_ITERATOR_INTERNAL *)Iterator;\r
e2c1104c
PG
98\r
99 // CurrentNode can be NULL, but InitialNode cannot.\r
100 if ((InternalIterator == NULL) ||\r
101 (InternalIterator->Mode != EAmlIteratorLinear) ||\r
102 !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||\r
731c67e1
MK
103 !IS_AML_NODE_VALID (InternalIterator->CurrentNode))\r
104 {\r
e2c1104c
PG
105 ASSERT (0);\r
106 return EFI_INVALID_PARAMETER;\r
107 }\r
108\r
109 // Get the next node according to the iteration mode.\r
110 InternalIterator->CurrentNode = AmlGetNextNode (\r
111 InternalIterator->CurrentNode\r
112 );\r
113\r
114 if (NextNode != NULL) {\r
731c67e1 115 *NextNode = (AML_NODE_HEADER *)InternalIterator->CurrentNode;\r
e2c1104c 116 }\r
731c67e1 117\r
e2c1104c
PG
118 return EFI_SUCCESS;\r
119}\r
120\r
121/** Move the current node of the iterator to the previous node,\r
122 according to the iteration mode selected.\r
123\r
124 If PrevNode is not NULL, return the previous node.\r
125\r
126 @param [in] Iterator Pointer to an iterator.\r
127 @param [out] PrevNode If not NULL, updated to the previous node.\r
128\r
129 @retval EFI_SUCCESS The function completed successfully.\r
130 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
131**/\r
132STATIC\r
133EFI_STATUS\r
134EFIAPI\r
135AmlIteratorGetPreviousLinear (\r
731c67e1
MK
136 IN AML_TREE_ITERATOR *Iterator,\r
137 OUT AML_NODE_HEADER **PrevNode\r
e2c1104c
PG
138 )\r
139{\r
731c67e1 140 AML_TREE_ITERATOR_INTERNAL *InternalIterator;\r
e2c1104c 141\r
731c67e1 142 InternalIterator = (AML_TREE_ITERATOR_INTERNAL *)Iterator;\r
e2c1104c
PG
143\r
144 // CurrentNode can be NULL, but InitialNode cannot.\r
145 if ((InternalIterator == NULL) ||\r
146 (InternalIterator->Mode != EAmlIteratorLinear) ||\r
147 !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||\r
731c67e1
MK
148 !IS_AML_NODE_VALID (InternalIterator->CurrentNode))\r
149 {\r
e2c1104c
PG
150 ASSERT (0);\r
151 return EFI_INVALID_PARAMETER;\r
152 }\r
153\r
154 // Get the previous node according to the iteration mode.\r
155 InternalIterator->CurrentNode = AmlGetPreviousNode (\r
156 InternalIterator->CurrentNode\r
157 );\r
158 if (PrevNode != NULL) {\r
731c67e1 159 *PrevNode = (AML_NODE_HEADER *)InternalIterator->CurrentNode;\r
e2c1104c 160 }\r
731c67e1 161\r
e2c1104c
PG
162 return EFI_SUCCESS;\r
163}\r
164\r
165/** Move the current node of the iterator to the next node,\r
166 according to the iteration mode selected.\r
167\r
168 If NextNode is not NULL, return the next node.\r
169\r
170 @param [in] Iterator Pointer to an iterator.\r
171 @param [out] NextNode If not NULL, updated to the next node.\r
172\r
173 @retval EFI_SUCCESS The function completed successfully.\r
174 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
175**/\r
176STATIC\r
177EFI_STATUS\r
178EFIAPI\r
179AmlIteratorGetNextBranch (\r
731c67e1
MK
180 IN AML_TREE_ITERATOR *Iterator,\r
181 OUT AML_NODE_HEADER **NextNode\r
e2c1104c
PG
182 )\r
183{\r
731c67e1
MK
184 AML_TREE_ITERATOR_INTERNAL *InternalIterator;\r
185 AML_NODE_HEADER *Node;\r
e2c1104c 186\r
731c67e1 187 InternalIterator = (AML_TREE_ITERATOR_INTERNAL *)Iterator;\r
e2c1104c
PG
188\r
189 // CurrentNode can be NULL, but InitialNode cannot.\r
190 if ((InternalIterator == NULL) ||\r
191 (InternalIterator->Mode != EAmlIteratorBranch) ||\r
192 !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||\r
731c67e1
MK
193 !IS_AML_NODE_VALID (InternalIterator->CurrentNode))\r
194 {\r
e2c1104c
PG
195 ASSERT (0);\r
196 return EFI_INVALID_PARAMETER;\r
197 }\r
198\r
199 Node = AmlGetNextNode (InternalIterator->CurrentNode);\r
200 // Check whether NextNode is a sibling of InitialNode.\r
201 if (AmlGetParent (Node) ==\r
731c67e1
MK
202 AmlGetParent ((AML_NODE_HEADER *)InternalIterator->InitialNode))\r
203 {\r
e2c1104c
PG
204 Node = NULL;\r
205 }\r
206\r
207 InternalIterator->CurrentNode = Node;\r
208\r
209 if (NextNode != NULL) {\r
210 *NextNode = Node;\r
211 }\r
731c67e1 212\r
e2c1104c
PG
213 return EFI_SUCCESS;\r
214}\r
215\r
216/** Move the current node of the iterator to the previous node,\r
217 according to the iteration mode selected.\r
218\r
219 If PrevNode is not NULL, return the previous node.\r
220\r
221 @param [in] Iterator Pointer to an iterator.\r
222 @param [out] PrevNode If not NULL, updated to the previous node.\r
223\r
224 @retval EFI_SUCCESS The function completed successfully.\r
225 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
226**/\r
227STATIC\r
228EFI_STATUS\r
229EFIAPI\r
230AmlIteratorGetPreviousBranch (\r
731c67e1
MK
231 IN AML_TREE_ITERATOR *Iterator,\r
232 OUT AML_NODE_HEADER **PrevNode\r
e2c1104c
PG
233 )\r
234{\r
731c67e1
MK
235 AML_TREE_ITERATOR_INTERNAL *InternalIterator;\r
236 AML_NODE_HEADER *Node;\r
e2c1104c 237\r
731c67e1 238 InternalIterator = (AML_TREE_ITERATOR_INTERNAL *)Iterator;\r
e2c1104c
PG
239\r
240 // CurrentNode can be NULL, but InitialNode cannot.\r
241 if ((InternalIterator == NULL) ||\r
242 (InternalIterator->Mode != EAmlIteratorBranch) ||\r
243 !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||\r
731c67e1
MK
244 !IS_AML_NODE_VALID (InternalIterator->CurrentNode))\r
245 {\r
e2c1104c
PG
246 ASSERT (0);\r
247 return EFI_INVALID_PARAMETER;\r
248 }\r
249\r
250 Node = AmlGetPreviousNode (InternalIterator->CurrentNode);\r
251 // Check whether PreviousNode is a sibling of InitialNode.\r
252 if (AmlGetParent (Node) ==\r
731c67e1
MK
253 AmlGetParent ((AML_NODE_HEADER *)InternalIterator->InitialNode))\r
254 {\r
e2c1104c
PG
255 Node = NULL;\r
256 }\r
257\r
258 InternalIterator->CurrentNode = Node;\r
259\r
260 if (PrevNode != NULL) {\r
261 *PrevNode = Node;\r
262 }\r
731c67e1 263\r
e2c1104c
PG
264 return EFI_SUCCESS;\r
265}\r
266\r
267/** Initialize an iterator.\r
268\r
269 Note: The caller must call AmlDeleteIterator () to free the memory\r
270 allocated for the iterator.\r
271\r
272 @param [in] Node Pointer to the node.\r
273 @param [in] IteratorMode Selected mode to traverse the tree.\r
274 @param [out] IteratorPtr Pointer holding the created iterator.\r
275\r
276 @retval EFI_SUCCESS The function completed successfully.\r
277 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
278 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
279**/\r
280EFI_STATUS\r
281EFIAPI\r
282AmlInitializeIterator (\r
731c67e1
MK
283 IN AML_NODE_HEADER *Node,\r
284 IN EAML_ITERATOR_MODE IteratorMode,\r
285 OUT AML_TREE_ITERATOR **IteratorPtr\r
e2c1104c
PG
286 )\r
287{\r
731c67e1 288 AML_TREE_ITERATOR_INTERNAL *InternalIterator;\r
e2c1104c
PG
289\r
290 if (!IS_AML_NODE_VALID (Node) ||\r
291 (IteratorMode <= EAmlIteratorUnknown) ||\r
292 (IteratorMode >= EAmlIteratorModeMax) ||\r
731c67e1
MK
293 (IteratorPtr == NULL))\r
294 {\r
e2c1104c
PG
295 ASSERT (0);\r
296 return EFI_INVALID_PARAMETER;\r
297 }\r
298\r
731c67e1
MK
299 *IteratorPtr = NULL;\r
300 InternalIterator = (AML_TREE_ITERATOR_INTERNAL *)AllocateZeroPool (\r
301 sizeof (\r
302 AML_TREE_ITERATOR_INTERNAL\r
303 )\r
304 );\r
e2c1104c
PG
305 if (InternalIterator == NULL) {\r
306 ASSERT (0);\r
307 return EFI_OUT_OF_RESOURCES;\r
308 }\r
309\r
731c67e1
MK
310 InternalIterator->InitialNode = Node;\r
311 InternalIterator->CurrentNode = Node;\r
312 InternalIterator->Mode = IteratorMode;\r
e2c1104c
PG
313 InternalIterator->Iterator.GetNode = AmlIteratorGetNode;\r
314\r
315 switch (InternalIterator->Mode) {\r
316 case EAmlIteratorLinear:\r
317 {\r
731c67e1 318 InternalIterator->Iterator.GetNext = AmlIteratorGetNextLinear;\r
e2c1104c
PG
319 InternalIterator->Iterator.GetPrevious = AmlIteratorGetPreviousLinear;\r
320 break;\r
321 }\r
322 case EAmlIteratorBranch:\r
323 {\r
731c67e1 324 InternalIterator->Iterator.GetNext = AmlIteratorGetNextBranch;\r
e2c1104c
PG
325 InternalIterator->Iterator.GetPrevious = AmlIteratorGetPreviousBranch;\r
326 break;\r
327 }\r
328 default:\r
329 {\r
330 ASSERT (0);\r
331 FreePool (InternalIterator);\r
332 return EFI_INVALID_PARAMETER;\r
333 }\r
334 } // switch\r
335\r
336 *IteratorPtr = &InternalIterator->Iterator;\r
337\r
338 return EFI_SUCCESS;\r
339}\r
340\r
341/** Delete an iterator.\r
342\r
343 Note: The caller must have first initialized the iterator with the\r
344 AmlInitializeIterator () function.\r
345\r
346 @param [in] Iterator Pointer to an iterator.\r
347\r
348 @retval EFI_SUCCESS The function completed successfully.\r
349 @retval EFI_INVALID_PARAMETER Invalid parameter.\r
350**/\r
351EFI_STATUS\r
352EFIAPI\r
353AmlDeleteIterator (\r
731c67e1 354 IN AML_TREE_ITERATOR *Iterator\r
e2c1104c
PG
355 )\r
356{\r
357 if (Iterator == NULL) {\r
358 ASSERT (0);\r
359 return EFI_INVALID_PARAMETER;\r
360 }\r
361\r
362 FreePool (Iterator);\r
363\r
364 return EFI_SUCCESS;\r
365}\r