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