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