]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Common / AmlLib / Api / AmlApi.c
1 /** @file
2 AML Api.
3
4 Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 /* Even though this file has access to the internal Node definition,
10 i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node
11 handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE,
12 etc.
13 Indeed, the functions in the "Api" folder should be implemented only
14 using the "safe" functions available in the "Include" folder. This
15 makes the functions available in the "Api" folder easy to export.
16 */
17 #include <AmlNodeDefines.h>
18
19 #include <AmlCoreInterface.h>
20 #include <AmlInclude.h>
21 #include <Api/AmlApiHelper.h>
22 #include <String/AmlString.h>
23
24 /** Update the name of a DeviceOp object node.
25
26 @param [in] DeviceOpNode Object node representing a Device.
27 Must have an OpCode=AML_NAME_OP, SubOpCode=0.
28 OpCode/SubOpCode.
29 DeviceOp object nodes are defined in ASL
30 using the "Device ()" function.
31 @param [in] NewNameString The new Device's name.
32 Must be a NULL-terminated ASL NameString
33 e.g.: "DEV0", "DV15.DEV0", etc.
34 The input string is copied.
35
36 @retval EFI_SUCCESS The function completed successfully.
37 @retval EFI_INVALID_PARAMETER Invalid parameter.
38 **/
39 EFI_STATUS
40 EFIAPI
41 AmlDeviceOpUpdateName (
42 IN AML_OBJECT_NODE_HANDLE DeviceOpNode,
43 IN CHAR8 *NewNameString
44 )
45 {
46 EFI_STATUS Status;
47
48 AML_DATA_NODE_HANDLE DeviceNameDataNode;
49 CHAR8 *NewAmlNameString;
50 UINT32 NewAmlNameStringSize;
51
52 // Check the input node is an object node.
53 if ((DeviceOpNode == NULL) ||
54 (AmlGetNodeType ((AML_NODE_HANDLE)DeviceOpNode) != EAmlNodeObject) ||
55 (!AmlNodeHasOpCode (DeviceOpNode, AML_EXT_OP, AML_EXT_DEVICE_OP)) ||
56 (NewNameString == NULL))
57 {
58 ASSERT (0);
59 return EFI_INVALID_PARAMETER;
60 }
61
62 // Get the Device's name, being a data node
63 // which is the 1st fixed argument (i.e. index 0).
64 DeviceNameDataNode = (AML_DATA_NODE_HANDLE)AmlGetFixedArgument (
65 DeviceOpNode,
66 EAmlParseIndexTerm0
67 );
68 if ((DeviceNameDataNode == NULL) ||
69 (AmlGetNodeType ((AML_NODE_HANDLE)DeviceNameDataNode) != EAmlNodeData) ||
70 (!AmlNodeHasDataType (DeviceNameDataNode, EAmlNodeDataTypeNameString)))
71 {
72 ASSERT (0);
73 return EFI_INVALID_PARAMETER;
74 }
75
76 Status = ConvertAslNameToAmlName (NewNameString, &NewAmlNameString);
77 if (EFI_ERROR (Status)) {
78 ASSERT (0);
79 return Status;
80 }
81
82 Status = AmlGetNameStringSize (NewAmlNameString, &NewAmlNameStringSize);
83 if (EFI_ERROR (Status)) {
84 ASSERT (0);
85 goto exit_handler;
86 }
87
88 // Update the Device's name node.
89 Status = AmlUpdateDataNode (
90 DeviceNameDataNode,
91 EAmlNodeDataTypeNameString,
92 (UINT8 *)NewAmlNameString,
93 NewAmlNameStringSize
94 );
95 ASSERT_EFI_ERROR (Status);
96
97 exit_handler:
98 FreePool (NewAmlNameString);
99 return Status;
100 }
101
102 /** Update an integer value defined by a NameOp object node.
103
104 For compatibility reasons, the NameOpNode must initially
105 contain an integer.
106
107 @param [in] NameOpNode NameOp object node.
108 Must have an OpCode=AML_NAME_OP, SubOpCode=0.
109 NameOp object nodes are defined in ASL
110 using the "Name ()" function.
111 @param [in] NewInt New Integer value to assign.
112 Must be a UINT64.
113
114 @retval EFI_SUCCESS The function completed successfully.
115 @retval EFI_INVALID_PARAMETER Invalid parameter.
116 **/
117 EFI_STATUS
118 EFIAPI
119 AmlNameOpUpdateInteger (
120 IN AML_OBJECT_NODE_HANDLE NameOpNode,
121 IN UINT64 NewInt
122 )
123 {
124 EFI_STATUS Status;
125 AML_OBJECT_NODE_HANDLE IntegerOpNode;
126
127 if ((NameOpNode == NULL) ||
128 (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) != EAmlNodeObject) ||
129 (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0)))
130 {
131 ASSERT (0);
132 return EFI_INVALID_PARAMETER;
133 }
134
135 // Get the Integer object node defined by the "Name ()" function:
136 // it must have an Integer OpCode (Byte/Word/DWord/QWord).
137 // It is the 2nd fixed argument (i.e. index 1) of the NameOp node.
138 // This can also be a ZeroOp or OneOp node.
139 IntegerOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
140 NameOpNode,
141 EAmlParseIndexTerm1
142 );
143 if ((IntegerOpNode == NULL) ||
144 (AmlGetNodeType ((AML_NODE_HANDLE)IntegerOpNode) != EAmlNodeObject))
145 {
146 ASSERT (0);
147 return EFI_INVALID_PARAMETER;
148 }
149
150 // Update the Integer value.
151 Status = AmlUpdateInteger (IntegerOpNode, NewInt);
152 ASSERT_EFI_ERROR (Status);
153
154 return Status;
155 }
156
157 /** Update a string value defined by a NameOp object node.
158
159 The NameOpNode must initially contain a string.
160 The EISAID ASL macro converts a string to an integer. This, it is
161 not accepted.
162
163 @param [in] NameOpNode NameOp object node.
164 Must have an OpCode=AML_NAME_OP, SubOpCode=0.
165 NameOp object nodes are defined in ASL
166 using the "Name ()" function.
167 @param [in] NewName New NULL terminated string to assign to
168 the NameOpNode.
169 The input string is copied.
170
171 @retval EFI_SUCCESS The function completed successfully.
172 @retval EFI_INVALID_PARAMETER Invalid parameter.
173 **/
174 EFI_STATUS
175 EFIAPI
176 AmlNameOpUpdateString (
177 IN AML_OBJECT_NODE_HANDLE NameOpNode,
178 IN CONST CHAR8 *NewName
179 )
180 {
181 EFI_STATUS Status;
182 AML_OBJECT_NODE_HANDLE StringOpNode;
183 AML_DATA_NODE_HANDLE StringDataNode;
184
185 if ((NameOpNode == NULL) ||
186 (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) != EAmlNodeObject) ||
187 (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0)))
188 {
189 ASSERT (0);
190 return EFI_INVALID_PARAMETER;
191 }
192
193 // Get the String object node defined by the "Name ()" function:
194 // it must have a string OpCode.
195 // It is the 2nd fixed argument (i.e. index 1) of the NameOp node.
196 StringOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
197 NameOpNode,
198 EAmlParseIndexTerm1
199 );
200 if ((StringOpNode == NULL) ||
201 (AmlGetNodeType ((AML_NODE_HANDLE)StringOpNode) != EAmlNodeObject))
202 {
203 ASSERT (0);
204 return EFI_INVALID_PARAMETER;
205 }
206
207 // Get the string data node.
208 // It is the 1st fixed argument (i.e. index 0) of the StringOpNode node.
209 StringDataNode = (AML_DATA_NODE_HANDLE)AmlGetFixedArgument (
210 StringOpNode,
211 EAmlParseIndexTerm0
212 );
213 if ((StringDataNode == NULL) ||
214 (AmlGetNodeType ((AML_NODE_HANDLE)StringDataNode) != EAmlNodeData))
215 {
216 ASSERT (0);
217 return EFI_INVALID_PARAMETER;
218 }
219
220 // Update the string value.
221 Status = AmlUpdateDataNode (
222 StringDataNode,
223 EAmlNodeDataTypeString,
224 (UINT8 *)NewName,
225 (UINT32)AsciiStrLen (NewName) + 1
226 );
227 ASSERT_EFI_ERROR (Status);
228
229 return Status;
230 }
231
232 /** Get the first Resource Data element contained in a named object.
233
234 In the following ASL code, the function will return the Resource Data
235 node corresponding to the "QWordMemory ()" ASL macro.
236 Name (_CRS, ResourceTemplate() {
237 QWordMemory (...) {...},
238 Interrupt (...) {...}
239 }
240 )
241
242 Note:
243 "_CRS" names defined as methods are not handled by this function.
244 They must be defined as names, using the "Name ()" statement.
245
246 @param [in] NameOpNode NameOp object node defining a named object.
247 Must have an OpCode=AML_NAME_OP, SubOpCode=0.
248 NameOp object nodes are defined in ASL
249 using the "Name ()" function.
250 @param [out] OutRdNode Pointer to the first Resource Data element of
251 the named object. A Resource Data element
252 is stored in a data node.
253
254 @retval EFI_SUCCESS The function completed successfully.
255 @retval EFI_INVALID_PARAMETER Invalid parameter.
256 **/
257 EFI_STATUS
258 EFIAPI
259 AmlNameOpGetFirstRdNode (
260 IN AML_OBJECT_NODE_HANDLE NameOpNode,
261 OUT AML_DATA_NODE_HANDLE *OutRdNode
262 )
263 {
264 AML_OBJECT_NODE_HANDLE BufferOpNode;
265 AML_DATA_NODE_HANDLE FirstRdNode;
266
267 if ((NameOpNode == NULL) ||
268 (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) != EAmlNodeObject) ||
269 (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0)) ||
270 (OutRdNode == NULL))
271 {
272 ASSERT (0);
273 return EFI_INVALID_PARAMETER;
274 }
275
276 *OutRdNode = NULL;
277
278 // Get the value of the variable which is represented as a BufferOp object
279 // node which is the 2nd fixed argument (i.e. index 1).
280 BufferOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
281 NameOpNode,
282 EAmlParseIndexTerm1
283 );
284 if ((BufferOpNode == NULL) ||
285 (AmlGetNodeType ((AML_NODE_HANDLE)BufferOpNode) != EAmlNodeObject) ||
286 (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0)))
287 {
288 ASSERT (0);
289 return EFI_INVALID_PARAMETER;
290 }
291
292 // Get the first Resource data node in the variable list of
293 // argument of the BufferOp node.
294 FirstRdNode = (AML_DATA_NODE_HANDLE)AmlGetNextVariableArgument (
295 (AML_NODE_HANDLE)BufferOpNode,
296 NULL
297 );
298 if ((FirstRdNode == NULL) ||
299 (AmlGetNodeType ((AML_NODE_HANDLE)FirstRdNode) != EAmlNodeData) ||
300 (!AmlNodeHasDataType (FirstRdNode, EAmlNodeDataTypeResourceData)))
301 {
302 ASSERT (0);
303 return EFI_INVALID_PARAMETER;
304 }
305
306 *OutRdNode = FirstRdNode;
307 return EFI_SUCCESS;
308 }
309
310 /** Get the Resource Data element following the CurrRdNode Resource Data.
311
312 In the following ASL code, if CurrRdNode corresponds to the first
313 "QWordMemory ()" ASL macro, the function will return the Resource Data
314 node corresponding to the "Interrupt ()" ASL macro.
315 Name (_CRS, ResourceTemplate() {
316 QwordMemory (...) {...},
317 Interrupt (...) {...}
318 }
319 )
320
321 Note:
322 "_CRS" names defined as methods are not handled by this function.
323 They must be defined as names, using the "Name ()" statement.
324
325 @param [in] CurrRdNode Pointer to the current Resource Data element of
326 the named object.
327 @param [out] OutRdNode Pointer to the Resource Data element following
328 the CurrRdNode.
329 Contain a NULL pointer if CurrRdNode is the
330 last Resource Data element in the list.
331 The "End Tag" is not considered as a resource
332 data element and is not returned.
333
334 @retval EFI_SUCCESS The function completed successfully.
335 @retval EFI_INVALID_PARAMETER Invalid parameter.
336 **/
337 EFI_STATUS
338 EFIAPI
339 AmlNameOpGetNextRdNode (
340 IN AML_DATA_NODE_HANDLE CurrRdNode,
341 OUT AML_DATA_NODE_HANDLE *OutRdNode
342 )
343 {
344 AML_OBJECT_NODE_HANDLE NameOpNode;
345 AML_OBJECT_NODE_HANDLE BufferOpNode;
346
347 if ((CurrRdNode == NULL) ||
348 (AmlGetNodeType ((AML_NODE_HANDLE)CurrRdNode) != EAmlNodeData) ||
349 (!AmlNodeHasDataType (CurrRdNode, EAmlNodeDataTypeResourceData)) ||
350 (OutRdNode == NULL))
351 {
352 ASSERT (0);
353 return EFI_INVALID_PARAMETER;
354 }
355
356 *OutRdNode = NULL;
357
358 // The parent of the CurrRdNode must be a BufferOp node.
359 BufferOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetParent (
360 (AML_NODE_HANDLE)CurrRdNode
361 );
362 if ((BufferOpNode == NULL) ||
363 (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0)))
364 {
365 ASSERT (0);
366 return EFI_INVALID_PARAMETER;
367 }
368
369 // The parent of the BufferOpNode must be a NameOp node.
370 NameOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetParent (
371 (AML_NODE_HANDLE)BufferOpNode
372 );
373 if ((NameOpNode == NULL) ||
374 (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0)))
375 {
376 ASSERT (0);
377 return EFI_INVALID_PARAMETER;
378 }
379
380 *OutRdNode = (AML_DATA_NODE_HANDLE)AmlGetNextVariableArgument (
381 (AML_NODE_HANDLE)BufferOpNode,
382 (AML_NODE_HANDLE)CurrRdNode
383 );
384
385 // If the Resource Data is an End Tag, return NULL.
386 if (AmlNodeHasRdDataType (
387 *OutRdNode,
388 AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME)
389 ))
390 {
391 *OutRdNode = NULL;
392 }
393
394 return EFI_SUCCESS;
395 }
396
397 // DEPRECATED APIS
398 #ifndef DISABLE_NEW_DEPRECATED_INTERFACES
399
400 /** DEPRECATED API
401
402 Get the first Resource Data element contained in a "_CRS" object.
403
404 In the following ASL code, the function will return the Resource Data
405 node corresponding to the "QWordMemory ()" ASL macro.
406 Name (_CRS, ResourceTemplate() {
407 QWordMemory (...) {...},
408 Interrupt (...) {...}
409 }
410 )
411
412 Note:
413 - The "_CRS" object must be declared using ASL "Name (Declare Named Object)".
414 - "_CRS" declared using ASL "Method (Declare Control Method)" is not
415 supported.
416
417 @ingroup UserApis
418
419 @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object.
420 Must have an OpCode=AML_NAME_OP, SubOpCode=0.
421 NameOp object nodes are defined in ASL
422 using the "Name ()" function.
423 @param [out] OutRdNode Pointer to the first Resource Data element of
424 the "_CRS" object. A Resource Data element
425 is stored in a data node.
426
427 @retval EFI_SUCCESS The function completed successfully.
428 @retval EFI_INVALID_PARAMETER Invalid parameter.
429 **/
430 EFI_STATUS
431 EFIAPI
432 AmlNameOpCrsGetFirstRdNode (
433 IN AML_OBJECT_NODE_HANDLE NameOpCrsNode,
434 OUT AML_DATA_NODE_HANDLE *OutRdNode
435 )
436 {
437 return AmlNameOpGetFirstRdNode (NameOpCrsNode, OutRdNode);
438 }
439
440 /** DEPRECATED API
441
442 Get the Resource Data element following the CurrRdNode Resource Data.
443
444 In the following ASL code, if CurrRdNode corresponds to the first
445 "QWordMemory ()" ASL macro, the function will return the Resource Data
446 node corresponding to the "Interrupt ()" ASL macro.
447 Name (_CRS, ResourceTemplate() {
448 QwordMemory (...) {...},
449 Interrupt (...) {...}
450 }
451 )
452
453 The CurrRdNode Resource Data node must be defined in an object named "_CRS"
454 and defined by a "Name ()" ASL function.
455
456 @ingroup UserApis
457
458 @param [in] CurrRdNode Pointer to the current Resource Data element of
459 the "_CRS" variable.
460 @param [out] OutRdNode Pointer to the Resource Data element following
461 the CurrRdNode.
462 Contain a NULL pointer if CurrRdNode is the
463 last Resource Data element in the list.
464 The "End Tag" is not considered as a resource
465 data element and is not returned.
466
467 @retval EFI_SUCCESS The function completed successfully.
468 @retval EFI_INVALID_PARAMETER Invalid parameter.
469 **/
470 EFI_STATUS
471 EFIAPI
472 AmlNameOpCrsGetNextRdNode (
473 IN AML_DATA_NODE_HANDLE CurrRdNode,
474 OUT AML_DATA_NODE_HANDLE *OutRdNode
475 )
476 {
477 return AmlNameOpGetNextRdNode (CurrRdNode, OutRdNode);
478 }
479
480 #endif // DISABLE_NEW_DEPRECATED_INTERFACES