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