]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Acpi/AcpiTableDxe/AmlOption.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / Acpi / AcpiTableDxe / AmlOption.c
CommitLineData
3dc8585e
JY
1/** @file\r
2 ACPI Sdt Protocol Driver\r
3\r
d1102dba 4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>\r
9d510e61 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
3dc8585e
JY
6\r
7**/\r
8\r
9#include "AcpiTable.h"\r
10\r
11/**\r
12 Retrieve option term according to AmlByteEncoding and Buffer.\r
d1102dba 13\r
3dc8585e
JY
14 @param[in] AmlByteEncoding AML Byte Encoding.\r
15 @param[in] Buffer AML buffer.\r
16 @param[in] MaxBufferSize AML buffer MAX size. The parser can not parse any data exceed this region.\r
17 @param[in] TermIndex Index of the data to retrieve from the object.\r
18 @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists\r
19 for the specified index.\r
20 @param[out] Data Upon return, points to the pointer to the data.\r
21 @param[out] DataSize Upon return, points to the size of Data.\r
d1102dba 22\r
3dc8585e
JY
23 @retval EFI_SUCCESS Success.\r
24 @retval EFI_INVALID_PARAMETER Buffer does not refer to a valid ACPI object.\r
25**/\r
26EFI_STATUS\r
27AmlParseOptionTerm (\r
1436aea4
MK
28 IN AML_BYTE_ENCODING *AmlByteEncoding,\r
29 IN UINT8 *Buffer,\r
30 IN UINTN MaxBufferSize,\r
31 IN AML_OP_PARSE_INDEX TermIndex,\r
32 OUT EFI_ACPI_DATA_TYPE *DataType,\r
33 OUT VOID **Data,\r
34 OUT UINTN *DataSize\r
3dc8585e
JY
35 )\r
36{\r
1436aea4
MK
37 AML_BYTE_ENCODING *ChildAmlByteEncoding;\r
38 EFI_STATUS Status;\r
3dc8585e
JY
39\r
40 if (DataType != NULL) {\r
41 *DataType = AmlTypeToAcpiType (AmlByteEncoding->Format[TermIndex - 1]);\r
42 }\r
1436aea4 43\r
3dc8585e
JY
44 if (Data != NULL) {\r
45 *Data = Buffer;\r
46 }\r
1436aea4 47\r
3dc8585e
JY
48 //\r
49 // Parse term according to AML type\r
50 //\r
51 switch (AmlByteEncoding->Format[TermIndex - 1]) {\r
1436aea4
MK
52 case AML_UINT8:\r
53 *DataSize = sizeof (UINT8);\r
54 break;\r
55 case AML_UINT16:\r
56 *DataSize = sizeof (UINT16);\r
57 break;\r
58 case AML_UINT32:\r
59 *DataSize = sizeof (UINT32);\r
60 break;\r
61 case AML_UINT64:\r
62 *DataSize = sizeof (UINT64);\r
63 break;\r
64 case AML_STRING:\r
65 *DataSize = AsciiStrSize ((CHAR8 *)Buffer);\r
66 break;\r
67 case AML_NAME:\r
3dc8585e
JY
68 Status = AmlGetNameStringSize (Buffer, DataSize);\r
69 if (EFI_ERROR (Status)) {\r
70 return EFI_INVALID_PARAMETER;\r
71 }\r
1436aea4 72\r
3dc8585e 73 break;\r
1436aea4
MK
74 case AML_OBJECT:\r
75 ChildAmlByteEncoding = AmlSearchByOpByte (Buffer);\r
76 if (ChildAmlByteEncoding == NULL) {\r
77 return EFI_INVALID_PARAMETER;\r
78 }\r
3dc8585e 79\r
1436aea4
MK
80 //\r
81 // NOTE: We need override DataType here, if there is a case the AML_OBJECT is AML_NAME.\r
82 // We need convert type from EFI_ACPI_DATA_TYPE_CHILD to EFI_ACPI_DATA_TYPE_NAME_STRING.\r
83 // We should not return CHILD because there is NO OpCode for NameString.\r
84 //\r
85 if ((ChildAmlByteEncoding->Attribute & AML_IS_NAME_CHAR) != 0) {\r
86 if (DataType != NULL) {\r
87 *DataType = AmlTypeToAcpiType (AML_NAME);\r
88 }\r
89\r
90 Status = AmlGetNameStringSize (Buffer, DataSize);\r
91 if (EFI_ERROR (Status)) {\r
92 return EFI_INVALID_PARAMETER;\r
93 }\r
94\r
95 break;\r
96 }\r
97\r
98 //\r
99 // It is real AML_OBJECT\r
100 //\r
101 *DataSize = AmlGetObjectSize (\r
102 ChildAmlByteEncoding,\r
103 Buffer,\r
104 MaxBufferSize\r
105 );\r
106 if (*DataSize == 0) {\r
107 return EFI_INVALID_PARAMETER;\r
108 }\r
109\r
110 break;\r
111 case AML_NONE:\r
3dc8585e
JY
112 //\r
113 // No term\r
114 //\r
1436aea4
MK
115 case AML_OPCODE:\r
116 default:\r
117 ASSERT (FALSE);\r
118 return EFI_INVALID_PARAMETER;\r
3dc8585e 119 }\r
1436aea4 120\r
3dc8585e
JY
121 if (*DataSize > MaxBufferSize) {\r
122 return EFI_INVALID_PARAMETER;\r
123 }\r
1436aea4 124\r
3dc8585e
JY
125 return EFI_SUCCESS;\r
126}\r
127\r
128/**\r
129 Retrieve information according to AmlByteEncoding and Buffer.\r
d1102dba 130\r
3dc8585e
JY
131 @param[in] AmlByteEncoding AML Byte Encoding.\r
132 @param[in] Buffer AML buffer.\r
133 @param[in] MaxBufferSize AML buffer MAX size. The parser can not parse any data exceed this region.\r
134 @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right\r
135 in the ACPI encoding, with index 0 always being the ACPI opcode.\r
136 @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists\r
137 for the specified index.\r
138 @param[out] Data Upon return, points to the pointer to the data.\r
139 @param[out] DataSize Upon return, points to the size of Data.\r
d1102dba 140\r
3dc8585e
JY
141 @retval EFI_SUCCESS Success.\r
142 @retval EFI_INVALID_PARAMETER Buffer does not refer to a valid ACPI object.\r
143**/\r
144EFI_STATUS\r
145AmlParseOptionCommon (\r
1436aea4
MK
146 IN AML_BYTE_ENCODING *AmlByteEncoding,\r
147 IN UINT8 *Buffer,\r
148 IN UINTN MaxBufferSize,\r
149 IN AML_OP_PARSE_INDEX Index,\r
150 OUT EFI_ACPI_DATA_TYPE *DataType,\r
151 OUT VOID **Data,\r
152 OUT UINTN *DataSize\r
3dc8585e
JY
153 )\r
154{\r
155 UINT8 *CurrentBuffer;\r
156 UINTN PkgLength;\r
157 UINTN OpLength;\r
158 UINTN PkgOffset;\r
159 AML_OP_PARSE_INDEX TermIndex;\r
160 EFI_STATUS Status;\r
161\r
162 ASSERT ((Index <= AmlByteEncoding->MaxIndex) || (Index == AML_OP_PARSE_INDEX_GET_SIZE));\r
163\r
164 //\r
165 // 0. Check if this is NAME string.\r
166 //\r
167 if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) != 0) {\r
168 //\r
169 // Only allow GET_SIZE\r
170 //\r
171 if (Index != AML_OP_PARSE_INDEX_GET_SIZE) {\r
172 return EFI_INVALID_PARAMETER;\r
173 }\r
1436aea4 174\r
3dc8585e
JY
175 //\r
176 // return NameString size\r
177 //\r
178 Status = AmlGetNameStringSize (Buffer, DataSize);\r
179 if (EFI_ERROR (Status)) {\r
180 return EFI_INVALID_PARAMETER;\r
181 }\r
1436aea4 182\r
3dc8585e
JY
183 if (*DataSize > MaxBufferSize) {\r
184 return EFI_INVALID_PARAMETER;\r
185 }\r
1436aea4 186\r
3dc8585e
JY
187 return EFI_SUCCESS;\r
188 }\r
189\r
190 //\r
191 // Not NAME string, start parsing\r
192 //\r
193 CurrentBuffer = Buffer;\r
194\r
195 //\r
196 // 1. Get OpCode\r
197 //\r
198 if (Index != AML_OP_PARSE_INDEX_GET_SIZE) {\r
199 *DataType = EFI_ACPI_DATA_TYPE_OPCODE;\r
1436aea4 200 *Data = (VOID *)CurrentBuffer;\r
3dc8585e 201 }\r
1436aea4 202\r
3dc8585e
JY
203 if (*CurrentBuffer == AML_EXT_OP) {\r
204 OpLength = 2;\r
205 } else {\r
206 OpLength = 1;\r
207 }\r
1436aea4 208\r
3dc8585e
JY
209 *DataSize = OpLength;\r
210 if (Index == AML_OP_PARSE_INDEX_GET_OPCODE) {\r
211 return EFI_SUCCESS;\r
212 }\r
1436aea4 213\r
3dc8585e
JY
214 if (OpLength > MaxBufferSize) {\r
215 return EFI_INVALID_PARAMETER;\r
216 }\r
1436aea4 217\r
3dc8585e
JY
218 CurrentBuffer += OpLength;\r
219\r
220 //\r
221 // 2. Skip PkgLength field, if have\r
222 //\r
223 if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) != 0) {\r
1436aea4 224 PkgOffset = AmlGetPkgLength (CurrentBuffer, &PkgLength);\r
3dc8585e
JY
225 //\r
226 // Override MaxBufferSize if it is valid PkgLength\r
227 //\r
228 if (OpLength + PkgLength > MaxBufferSize) {\r
229 return EFI_INVALID_PARAMETER;\r
230 } else {\r
231 MaxBufferSize = OpLength + PkgLength;\r
232 }\r
233 } else {\r
234 PkgOffset = 0;\r
235 PkgLength = 0;\r
236 }\r
1436aea4 237\r
3dc8585e
JY
238 CurrentBuffer += PkgOffset;\r
239\r
240 //\r
241 // 3. Get Term one by one.\r
242 //\r
243 TermIndex = AML_OP_PARSE_INDEX_GET_TERM1;\r
244 while ((Index >= TermIndex) && (TermIndex <= AmlByteEncoding->MaxIndex) && ((UINTN)CurrentBuffer < (UINTN)Buffer + MaxBufferSize)) {\r
245 Status = AmlParseOptionTerm (\r
246 AmlByteEncoding,\r
247 CurrentBuffer,\r
248 (UINTN)Buffer + MaxBufferSize - (UINTN)CurrentBuffer,\r
249 TermIndex,\r
250 DataType,\r
251 Data,\r
252 DataSize\r
253 );\r
254 if (EFI_ERROR (Status)) {\r
255 return EFI_INVALID_PARAMETER;\r
256 }\r
257\r
258 if (Index == TermIndex) {\r
259 //\r
260 // Done\r
261 //\r
262 return EFI_SUCCESS;\r
263 }\r
264\r
265 //\r
266 // Parse next one\r
267 //\r
268 CurrentBuffer += *DataSize;\r
1436aea4 269 TermIndex++;\r
3dc8585e
JY
270 }\r
271\r
272 //\r
273 // Finish all options, but no option found.\r
274 //\r
275 if ((UINTN)CurrentBuffer > (UINTN)Buffer + MaxBufferSize) {\r
276 return EFI_INVALID_PARAMETER;\r
277 }\r
1436aea4 278\r
3dc8585e
JY
279 if ((UINTN)CurrentBuffer == (UINTN)Buffer + MaxBufferSize) {\r
280 if (Index != AML_OP_PARSE_INDEX_GET_SIZE) {\r
281 return EFI_INVALID_PARAMETER;\r
282 }\r
283 }\r
284\r
285 //\r
286 // 4. Finish parsing all node, return size\r
287 //\r
288 ASSERT (Index == AML_OP_PARSE_INDEX_GET_SIZE);\r
289 if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) != 0) {\r
290 *DataSize = OpLength + PkgLength;\r
291 } else {\r
292 *DataSize = (UINTN)CurrentBuffer - (UINTN)Buffer;\r
293 }\r
294\r
295 return EFI_SUCCESS;\r
296}\r
297\r
298/**\r
299 Return object size.\r
d1102dba 300\r
3dc8585e
JY
301 @param[in] AmlByteEncoding AML Byte Encoding.\r
302 @param[in] Buffer AML object buffer.\r
303 @param[in] MaxBufferSize AML object buffer MAX size. The parser can not parse any data exceed this region.\r
d1102dba 304\r
3dc8585e
JY
305 @return Size of the object.\r
306**/\r
307UINTN\r
308AmlGetObjectSize (\r
1436aea4
MK
309 IN AML_BYTE_ENCODING *AmlByteEncoding,\r
310 IN UINT8 *Buffer,\r
311 IN UINTN MaxBufferSize\r
3dc8585e
JY
312 )\r
313{\r
1436aea4
MK
314 EFI_STATUS Status;\r
315 UINTN DataSize;\r
3dc8585e
JY
316\r
317 Status = AmlParseOptionCommon (\r
1436aea4
MK
318 AmlByteEncoding,\r
319 Buffer,\r
320 MaxBufferSize,\r
321 AML_OP_PARSE_INDEX_GET_SIZE,\r
322 NULL,\r
323 NULL,\r
324 &DataSize\r
325 );\r
3dc8585e
JY
326 if (EFI_ERROR (Status)) {\r
327 return 0;\r
328 } else {\r
329 return DataSize;\r
330 }\r
331}\r
332\r
333/**\r
334 Return object name.\r
d1102dba 335\r
3dc8585e 336 @param[in] AmlHandle AML handle.\r
d1102dba 337\r
3dc8585e
JY
338 @return Name of the object.\r
339**/\r
340CHAR8 *\r
341AmlGetObjectName (\r
1436aea4 342 IN EFI_AML_HANDLE *AmlHandle\r
3dc8585e
JY
343 )\r
344{\r
345 AML_BYTE_ENCODING *AmlByteEncoding;\r
346 VOID *NameString;\r
347 UINTN NameSize;\r
348 AML_OP_PARSE_INDEX TermIndex;\r
349 EFI_STATUS Status;\r
350 EFI_ACPI_DATA_TYPE DataType;\r
351\r
352 AmlByteEncoding = AmlHandle->AmlByteEncoding;\r
353\r
354 ASSERT ((AmlByteEncoding->Attribute & AML_IN_NAMESPACE) != 0);\r
355\r
356 //\r
af3833ac 357 // Find out Last Name index, according to OpCode table.\r
3dc8585e
JY
358 // The last name will be the node name by design.\r
359 //\r
360 TermIndex = AmlByteEncoding->MaxIndex;\r
361 for (TermIndex = AmlByteEncoding->MaxIndex; TermIndex > 0; TermIndex--) {\r
362 if (AmlByteEncoding->Format[TermIndex - 1] == AML_NAME) {\r
363 break;\r
364 }\r
365 }\r
1436aea4 366\r
3dc8585e
JY
367 ASSERT (TermIndex != 0);\r
368\r
369 //\r
370 // Get Name for this node.\r
371 //\r
372 Status = AmlParseOptionHandleCommon (\r
373 AmlHandle,\r
374 TermIndex,\r
375 &DataType,\r
376 &NameString,\r
377 &NameSize\r
378 );\r
379 if (EFI_ERROR (Status)) {\r
380 return NULL;\r
381 }\r
1436aea4 382\r
3dc8585e
JY
383 ASSERT (DataType == EFI_ACPI_DATA_TYPE_NAME_STRING);\r
384\r
385 return NameString;\r
386}\r
387\r
388/**\r
389 Return offset of last option.\r
d1102dba 390\r
3dc8585e
JY
391 @param[in] AmlHandle AML Handle.\r
392 @param[out] Buffer Upon return, points to the offset after last option.\r
d1102dba 393\r
3dc8585e
JY
394 @retval EFI_SUCCESS Success.\r
395 @retval EFI_INVALID_PARAMETER AmlHandle does not refer to a valid ACPI object.\r
396**/\r
397EFI_STATUS\r
398AmlGetOffsetAfterLastOption (\r
1436aea4
MK
399 IN EFI_AML_HANDLE *AmlHandle,\r
400 OUT UINT8 **Buffer\r
3dc8585e
JY
401 )\r
402{\r
403 EFI_ACPI_DATA_TYPE DataType;\r
404 VOID *Data;\r
405 UINTN DataSize;\r
406 EFI_STATUS Status;\r
407\r
408 Status = AmlParseOptionHandleCommon (\r
409 AmlHandle,\r
410 AmlHandle->AmlByteEncoding->MaxIndex,\r
411 &DataType,\r
412 &Data,\r
413 &DataSize\r
414 );\r
415 if (EFI_ERROR (Status)) {\r
416 return EFI_INVALID_PARAMETER;\r
417 }\r
418\r
419 //\r
420 // We need to parse the rest buffer after last node.\r
421 //\r
422 *Buffer = (UINT8 *)((UINTN)Data + DataSize);\r
423\r
424 //\r
425 // We need skip PkgLength if no Option\r
426 //\r
427 if (DataType == EFI_ACPI_DATA_TYPE_OPCODE) {\r
428 *Buffer += AmlGetPkgLength (*Buffer, &DataSize);\r
429 }\r
1436aea4 430\r
3dc8585e
JY
431 return EFI_SUCCESS;\r
432}\r
433\r
434/**\r
435 Retrieve information according to AmlHandle\r
d1102dba 436\r
3dc8585e
JY
437 @param[in] AmlHandle AML handle.\r
438 @param[in] Index Index of the data to retrieve from the object. In general, indexes read from left-to-right\r
439 in the ACPI encoding, with index 0 always being the ACPI opcode.\r
440 @param[out] DataType Points to the returned data type or EFI_ACPI_DATA_TYPE_NONE if no data exists\r
441 for the specified index.\r
442 @param[out] Data Upon return, points to the pointer to the data.\r
443 @param[out] DataSize Upon return, points to the size of Data.\r
d1102dba 444\r
3dc8585e
JY
445 @retval EFI_SUCCESS Success.\r
446 @retval EFI_INVALID_PARAMETER AmlHandle does not refer to a valid ACPI object.\r
447**/\r
448EFI_STATUS\r
449AmlParseOptionHandleCommon (\r
1436aea4
MK
450 IN EFI_AML_HANDLE *AmlHandle,\r
451 IN AML_OP_PARSE_INDEX Index,\r
452 OUT EFI_ACPI_DATA_TYPE *DataType,\r
453 OUT VOID **Data,\r
454 OUT UINTN *DataSize\r
3dc8585e
JY
455 )\r
456{\r
457 return AmlParseOptionCommon (\r
458 AmlHandle->AmlByteEncoding,\r
459 AmlHandle->Buffer,\r
460 AmlHandle->Size,\r
461 Index,\r
462 DataType,\r
463 Data,\r
464 DataSize\r
465 );\r
466}\r