blob: 5981b65cd3d3e70a67f4e6f27dcac4c280166485 [file] [log] [blame]
Erik Schmauss95857632018-03-14 16:13:07 -07001// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
Robert Moore73459f72005-06-24 00:00:00 -04002/******************************************************************************
3 *
4 * Module Name: psloop - Main AML parse loop
5 *
Bob Mooreda6f8322018-01-04 10:06:38 -08006 * Copyright (C) 2000 - 2018, Intel Corp.
Robert Moore73459f72005-06-24 00:00:00 -04007 *
Erik Schmauss95857632018-03-14 16:13:07 -07008 *****************************************************************************/
Robert Moore73459f72005-06-24 00:00:00 -04009
Robert Moore73459f72005-06-24 00:00:00 -040010/*
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030011 * Parse the AML and build an operation tree as most interpreters, (such as
12 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
13 * to tightly constrain stack and dynamic memory usage. Parsing is kept
14 * flexible and the code fairly compact by parsing based on a list of AML
15 * opcode templates in aml_op_info[].
Robert Moore73459f72005-06-24 00:00:00 -040016 */
17
18#include <acpi/acpi.h>
Len Browne2f7a772009-01-09 00:30:03 -050019#include "accommon.h"
Lv Zhengab6c5732015-07-23 12:52:59 +080020#include "acinterp.h"
Len Browne2f7a772009-01-09 00:30:03 -050021#include "acparser.h"
22#include "acdispat.h"
23#include "amlcode.h"
Bob Moore9cf7ade2017-04-28 08:53:22 +080024#include "acconvert.h"
Robert Moore73459f72005-06-24 00:00:00 -040025
26#define _COMPONENT ACPI_PARSER
Len Brown4be44fc2005-08-05 00:44:28 -040027ACPI_MODULE_NAME("psloop")
Robert Moore73459f72005-06-24 00:00:00 -040028
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030029/* Local prototypes */
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030030static acpi_status
31acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
32 u8 * aml_op_start, union acpi_parse_object *op);
33
Lin Ming7f0c8262009-08-13 14:03:15 +080034static void
Lin Ming9a884ab2009-11-12 09:57:53 +080035acpi_ps_link_module_code(union acpi_parse_object *parent_op,
36 u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
Lin Ming7f0c8262009-08-13 14:03:15 +080037
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030038/*******************************************************************************
39 *
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030040 * FUNCTION: acpi_ps_get_arguments
41 *
42 * PARAMETERS: walk_state - Current state
43 * aml_op_start - Op start in AML
Bob Mooreba494be2012-07-12 09:40:10 +080044 * op - Current Op
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030045 *
46 * RETURN: Status
47 *
48 * DESCRIPTION: Get arguments for passed Op.
49 *
50 ******************************************************************************/
51
52static acpi_status
53acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
54 u8 * aml_op_start, union acpi_parse_object *op)
55{
56 acpi_status status = AE_OK;
57 union acpi_parse_object *arg = NULL;
Lin Ming7f0c8262009-08-13 14:03:15 +080058 const struct acpi_opcode_info *op_info;
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030059
60 ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
61
Bob Moorece87e092016-12-28 15:29:43 +080062 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
63 "Get arguments for opcode [%s]\n",
64 op->common.aml_op_name));
65
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030066 switch (op->common.aml_opcode) {
67 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
68 case AML_WORD_OP: /* AML_WORDDATA_ARG */
69 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
70 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
71 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
72
73 /* Fill in constant or string argument directly */
74
75 acpi_ps_get_next_simple_arg(&(walk_state->parser_state),
76 GET_CURRENT_ARG_TYPE(walk_state->
77 arg_types),
78 op);
79 break;
80
81 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
82
Bob Moore89438f92015-12-29 14:00:07 +080083 status = acpi_ps_get_next_namepath(walk_state,
84 &(walk_state->parser_state),
85 op,
86 ACPI_POSSIBLE_METHOD_CALL);
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +030087 if (ACPI_FAILURE(status)) {
88 return_ACPI_STATUS(status);
89 }
90
91 walk_state->arg_types = 0;
92 break;
93
94 default:
95 /*
96 * Op is not a constant or string, append each argument to the Op
97 */
Bob Moore1fad8732015-12-29 13:54:36 +080098 while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
99 !walk_state->arg_count) {
Lv Zheng83482f72015-07-23 12:52:11 +0800100 walk_state->aml = walk_state->parser_state.aml;
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300101
Bob Moore9cf7ade2017-04-28 08:53:22 +0800102 switch (op->common.aml_opcode) {
103 case AML_METHOD_OP:
104 case AML_BUFFER_OP:
105 case AML_PACKAGE_OP:
106 case AML_VARIABLE_PACKAGE_OP:
107 case AML_WHILE_OP:
108
109 break;
110
111 default:
112
113 ASL_CV_CAPTURE_COMMENTS(walk_state);
114 break;
115 }
116
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300117 status =
118 acpi_ps_get_next_arg(walk_state,
119 &(walk_state->parser_state),
120 GET_CURRENT_ARG_TYPE
121 (walk_state->arg_types), &arg);
122 if (ACPI_FAILURE(status)) {
123 return_ACPI_STATUS(status);
124 }
125
126 if (arg) {
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300127 acpi_ps_append_arg(op, arg);
128 }
129
130 INCREMENT_ARG_LIST(walk_state->arg_types);
131 }
132
Bob Moorea62a7112017-08-03 14:27:22 +0800133 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
Bob Moore1ef63232018-02-15 13:09:28 -0800134 "Final argument count: %8.8X pass %u\n",
Bob Moorea62a7112017-08-03 14:27:22 +0800135 walk_state->arg_count,
136 walk_state->pass_number));
137
Lin Ming7f0c8262009-08-13 14:03:15 +0800138 /*
139 * Handle executable code at "module-level". This refers to
140 * executable opcodes that appear outside of any control method.
141 */
142 if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300143 ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
144 /*
145 * We want to skip If/Else/While constructs during Pass1 because we
146 * want to actually conditionally execute the code during Pass2.
147 *
148 * Except for disassembly, where we always want to walk the
149 * If/Else/While packages
150 */
151 switch (op->common.aml_opcode) {
152 case AML_IF_OP:
153 case AML_ELSE_OP:
154 case AML_WHILE_OP:
Lin Ming7f0c8262009-08-13 14:03:15 +0800155 /*
156 * Currently supported module-level opcodes are:
157 * IF/ELSE/WHILE. These appear to be the most common,
158 * and easiest to support since they open an AML
159 * package.
160 */
161 if (walk_state->pass_number ==
162 ACPI_IMODE_LOAD_PASS1) {
Lin Ming9a884ab2009-11-12 09:57:53 +0800163 acpi_ps_link_module_code(op->common.
164 parent,
165 aml_op_start,
166 (u32)
167 (walk_state->
Lin Ming7f0c8262009-08-13 14:03:15 +0800168 parser_state.
169 pkg_end -
Lin Ming9a884ab2009-11-12 09:57:53 +0800170 aml_op_start),
Lin Ming7f0c8262009-08-13 14:03:15 +0800171 walk_state->
172 owner_id);
173 }
174
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300175 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
176 "Pass1: Skipping an If/Else/While body\n"));
177
178 /* Skip body of if/else/while in pass 1 */
179
180 walk_state->parser_state.aml =
181 walk_state->parser_state.pkg_end;
182 walk_state->arg_count = 0;
183 break;
184
185 default:
Lin Ming7f0c8262009-08-13 14:03:15 +0800186 /*
187 * Check for an unsupported executable opcode at module
188 * level. We must be in PASS1, the parent must be a SCOPE,
189 * The opcode class must be EXECUTE, and the opcode must
190 * not be an argument to another opcode.
191 */
192 if ((walk_state->pass_number ==
193 ACPI_IMODE_LOAD_PASS1)
194 && (op->common.parent->common.aml_opcode ==
195 AML_SCOPE_OP)) {
196 op_info =
197 acpi_ps_get_opcode_info(op->common.
198 aml_opcode);
199 if ((op_info->class ==
200 AML_CLASS_EXECUTE) && (!arg)) {
201 ACPI_WARNING((AE_INFO,
Bob Moore00eb3252012-10-31 02:27:48 +0000202 "Unsupported module-level executable opcode "
203 "0x%.2X at table offset 0x%.4X",
204 op->common.
205 aml_opcode,
206 (u32)
207 (ACPI_PTR_DIFF
208 (aml_op_start,
209 walk_state->
210 parser_state.
211 aml_start) +
212 sizeof(struct
213 acpi_table_header))));
Lin Ming7f0c8262009-08-13 14:03:15 +0800214 }
215 }
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300216 break;
217 }
218 }
Lin Ming7f0c8262009-08-13 14:03:15 +0800219
220 /* Special processing for certain opcodes */
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300221
222 switch (op->common.aml_opcode) {
223 case AML_METHOD_OP:
224 /*
225 * Skip parsing of control method because we don't have enough
226 * info in the first pass to parse it correctly.
227 *
228 * Save the length and address of the body
229 */
230 op->named.data = walk_state->parser_state.aml;
231 op->named.length = (u32)
232 (walk_state->parser_state.pkg_end -
233 walk_state->parser_state.aml);
234
235 /* Skip body of method */
236
237 walk_state->parser_state.aml =
238 walk_state->parser_state.pkg_end;
239 walk_state->arg_count = 0;
240 break;
241
242 case AML_BUFFER_OP:
243 case AML_PACKAGE_OP:
Bob Moore9ff5a21a2017-04-26 16:18:40 +0800244 case AML_VARIABLE_PACKAGE_OP:
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300245
246 if ((op->common.parent) &&
247 (op->common.parent->common.aml_opcode ==
248 AML_NAME_OP)
249 && (walk_state->pass_number <=
250 ACPI_IMODE_LOAD_PASS2)) {
Bob Moorea62a7112017-08-03 14:27:22 +0800251 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
252 "Setup Package/Buffer: Pass %u, AML Ptr: %p\n",
253 walk_state->pass_number,
254 aml_op_start));
255
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300256 /*
257 * Skip parsing of Buffers and Packages because we don't have
258 * enough info in the first pass to parse them correctly.
259 */
260 op->named.data = aml_op_start;
261 op->named.length = (u32)
262 (walk_state->parser_state.pkg_end -
263 aml_op_start);
264
265 /* Skip body */
266
267 walk_state->parser_state.aml =
268 walk_state->parser_state.pkg_end;
269 walk_state->arg_count = 0;
270 }
271 break;
272
273 case AML_WHILE_OP:
274
275 if (walk_state->control_state) {
276 walk_state->control_state->control.package_end =
277 walk_state->parser_state.pkg_end;
278 }
279 break;
280
281 default:
282
283 /* No action for all other opcodes */
Chao Guan1d1ea1b2013-06-08 00:58:14 +0000284
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300285 break;
286 }
287
288 break;
289 }
290
291 return_ACPI_STATUS(AE_OK);
292}
293
294/*******************************************************************************
295 *
Lin Ming7f0c8262009-08-13 14:03:15 +0800296 * FUNCTION: acpi_ps_link_module_code
297 *
Lin Ming9a884ab2009-11-12 09:57:53 +0800298 * PARAMETERS: parent_op - Parent parser op
299 * aml_start - Pointer to the AML
Lin Ming7f0c8262009-08-13 14:03:15 +0800300 * aml_length - Length of executable AML
301 * owner_id - owner_id of module level code
302 *
303 * RETURN: None.
304 *
305 * DESCRIPTION: Wrap the module-level code with a method object and link the
306 * object to the global list. Note, the mutex field of the method
307 * object is used to link multiple module-level code objects.
308 *
309 ******************************************************************************/
310
311static void
Lin Ming9a884ab2009-11-12 09:57:53 +0800312acpi_ps_link_module_code(union acpi_parse_object *parent_op,
313 u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
Lin Ming7f0c8262009-08-13 14:03:15 +0800314{
315 union acpi_operand_object *prev;
316 union acpi_operand_object *next;
317 union acpi_operand_object *method_obj;
Lin Ming9a884ab2009-11-12 09:57:53 +0800318 struct acpi_namespace_node *parent_node;
Lin Ming7f0c8262009-08-13 14:03:15 +0800319
Bob Moore25823e72015-08-25 10:29:45 +0800320 ACPI_FUNCTION_TRACE(ps_link_module_code);
321
Lin Ming7f0c8262009-08-13 14:03:15 +0800322 /* Get the tail of the list */
323
324 prev = next = acpi_gbl_module_code_list;
325 while (next) {
326 prev = next;
327 next = next->method.mutex;
328 }
329
330 /*
331 * Insert the module level code into the list. Merge it if it is
332 * adjacent to the previous element.
333 */
334 if (!prev ||
335 ((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
336
337 /* Create, initialize, and link a new temporary method object */
338
339 method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
340 if (!method_obj) {
Bob Moore25823e72015-08-25 10:29:45 +0800341 return_VOID;
Lin Ming7f0c8262009-08-13 14:03:15 +0800342 }
343
Bob Moore25823e72015-08-25 10:29:45 +0800344 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
345 "Create/Link new code block: %p\n",
346 method_obj));
347
Lin Ming9a884ab2009-11-12 09:57:53 +0800348 if (parent_op->common.node) {
349 parent_node = parent_op->common.node;
350 } else {
351 parent_node = acpi_gbl_root_node;
352 }
353
Lin Ming7f0c8262009-08-13 14:03:15 +0800354 method_obj->method.aml_start = aml_start;
355 method_obj->method.aml_length = aml_length;
356 method_obj->method.owner_id = owner_id;
Lin Ming26294842011-01-12 09:19:43 +0800357 method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
Lin Ming7f0c8262009-08-13 14:03:15 +0800358
Lin Ming9a884ab2009-11-12 09:57:53 +0800359 /*
360 * Save the parent node in next_object. This is cheating, but we
361 * don't want to expand the method object.
362 */
363 method_obj->method.next_object =
364 ACPI_CAST_PTR(union acpi_operand_object, parent_node);
365
Lin Ming7f0c8262009-08-13 14:03:15 +0800366 if (!prev) {
367 acpi_gbl_module_code_list = method_obj;
368 } else {
369 prev->method.mutex = method_obj;
370 }
371 } else {
Bob Moore25823e72015-08-25 10:29:45 +0800372 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
373 "Appending to existing code block: %p\n",
374 prev));
375
Lin Ming7f0c8262009-08-13 14:03:15 +0800376 prev->method.aml_length += aml_length;
377 }
Bob Moore25823e72015-08-25 10:29:45 +0800378
379 return_VOID;
Lin Ming7f0c8262009-08-13 14:03:15 +0800380}
381
382/*******************************************************************************
383 *
Robert Moore73459f72005-06-24 00:00:00 -0400384 * FUNCTION: acpi_ps_parse_loop
385 *
386 * PARAMETERS: walk_state - Current state
387 *
388 * RETURN: Status
389 *
390 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
391 * a tree of ops.
392 *
393 ******************************************************************************/
394
Len Brown4be44fc2005-08-05 00:44:28 -0400395acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
Robert Moore73459f72005-06-24 00:00:00 -0400396{
Len Brown4be44fc2005-08-05 00:44:28 -0400397 acpi_status status = AE_OK;
Len Brown4be44fc2005-08-05 00:44:28 -0400398 union acpi_parse_object *op = NULL; /* current op */
Len Brown4be44fc2005-08-05 00:44:28 -0400399 struct acpi_parse_state *parser_state;
400 u8 *aml_op_start = NULL;
Robert Moore73459f72005-06-24 00:00:00 -0400401
Bob Mooreb229cf92006-04-21 17:15:00 -0400402 ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
Robert Moore73459f72005-06-24 00:00:00 -0400403
404 if (walk_state->descending_callback == NULL) {
Len Brown4be44fc2005-08-05 00:44:28 -0400405 return_ACPI_STATUS(AE_BAD_PARAMETER);
Robert Moore73459f72005-06-24 00:00:00 -0400406 }
407
408 parser_state = &walk_state->parser_state;
409 walk_state->arg_types = 0;
410
411#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
412
413 if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400414
Robert Moore73459f72005-06-24 00:00:00 -0400415 /* We are restarting a preempted control method */
416
Len Brown4be44fc2005-08-05 00:44:28 -0400417 if (acpi_ps_has_completed_scope(parser_state)) {
Robert Moore73459f72005-06-24 00:00:00 -0400418 /*
419 * We must check if a predicate to an IF or WHILE statement
420 * was just completed
421 */
422 if ((parser_state->scope->parse_scope.op) &&
Len Brown4be44fc2005-08-05 00:44:28 -0400423 ((parser_state->scope->parse_scope.op->common.
424 aml_opcode == AML_IF_OP)
425 || (parser_state->scope->parse_scope.op->common.
426 aml_opcode == AML_WHILE_OP))
427 && (walk_state->control_state)
428 && (walk_state->control_state->common.state ==
429 ACPI_CONTROL_PREDICATE_EXECUTING)) {
Robert Moore73459f72005-06-24 00:00:00 -0400430 /*
431 * A predicate was just completed, get the value of the
432 * predicate and branch based on that value
433 */
434 walk_state->op = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400435 status =
436 acpi_ds_get_predicate_value(walk_state,
437 ACPI_TO_POINTER
438 (TRUE));
439 if (ACPI_FAILURE(status)
440 && ((status & AE_CODE_MASK) !=
441 AE_CODE_CONTROL)) {
Robert Moore73459f72005-06-24 00:00:00 -0400442 if (status == AE_AML_NO_RETURN_VALUE) {
Bob Mooreb8e4d892006-01-27 16:43:00 -0500443 ACPI_EXCEPTION((AE_INFO, status,
444 "Invoked method did not return a value"));
Robert Moore73459f72005-06-24 00:00:00 -0400445 }
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300446
Bob Mooreb8e4d892006-01-27 16:43:00 -0500447 ACPI_EXCEPTION((AE_INFO, status,
Bob Mooreb229cf92006-04-21 17:15:00 -0400448 "GetPredicate Failed"));
Len Brown4be44fc2005-08-05 00:44:28 -0400449 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400450 }
451
Len Brown4be44fc2005-08-05 00:44:28 -0400452 status =
453 acpi_ps_next_parse_state(walk_state, op,
454 status);
Robert Moore73459f72005-06-24 00:00:00 -0400455 }
456
Len Brown4be44fc2005-08-05 00:44:28 -0400457 acpi_ps_pop_scope(parser_state, &op,
458 &walk_state->arg_types,
459 &walk_state->arg_count);
460 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
461 "Popped scope, Op=%p\n", op));
462 } else if (walk_state->prev_op) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400463
Robert Moore73459f72005-06-24 00:00:00 -0400464 /* We were in the middle of an op */
465
466 op = walk_state->prev_op;
467 walk_state->arg_types = walk_state->prev_arg_types;
468 }
469 }
470#endif
471
472 /* Iterative parsing loop, while there is more AML to process: */
473
474 while ((parser_state->aml < parser_state->aml_end) || (op)) {
Bob Moore9cf7ade2017-04-28 08:53:22 +0800475 ASL_CV_CAPTURE_COMMENTS(walk_state);
476
Robert Moore73459f72005-06-24 00:00:00 -0400477 aml_op_start = parser_state->aml;
478 if (!op) {
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300479 status =
480 acpi_ps_create_op(walk_state, aml_op_start, &op);
481 if (ACPI_FAILURE(status)) {
482 if (status == AE_CTRL_PARSE_CONTINUE) {
Robert Moore73459f72005-06-24 00:00:00 -0400483 continue;
484 }
485
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300486 if (status == AE_CTRL_PARSE_PENDING) {
Robert Moore73459f72005-06-24 00:00:00 -0400487 status = AE_OK;
Robert Moore73459f72005-06-24 00:00:00 -0400488 }
489
Bob Moore22b5afc2014-03-24 14:49:00 +0800490 if (status == AE_CTRL_TERMINATE) {
491 return_ACPI_STATUS(status);
492 }
493
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300494 status =
495 acpi_ps_complete_op(walk_state, &op,
496 status);
Len Brown4be44fc2005-08-05 00:44:28 -0400497 if (ACPI_FAILURE(status)) {
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300498 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400499 }
500
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300501 continue;
Robert Moore73459f72005-06-24 00:00:00 -0400502 }
503
Lv Zhengab6c5732015-07-23 12:52:59 +0800504 acpi_ex_start_trace_opcode(op, walk_state);
Robert Moore73459f72005-06-24 00:00:00 -0400505 }
506
Robert Moore73459f72005-06-24 00:00:00 -0400507 /*
508 * Start arg_count at zero because we don't know if there are
509 * any args yet
510 */
511 walk_state->arg_count = 0;
512
Bob Moore9cf7ade2017-04-28 08:53:22 +0800513 switch (op->common.aml_opcode) {
514 case AML_BYTE_OP:
515 case AML_WORD_OP:
516 case AML_DWORD_OP:
517 case AML_QWORD_OP:
518
519 break;
520
521 default:
522
523 ASL_CV_CAPTURE_COMMENTS(walk_state);
524 break;
525 }
526
Robert Moore73459f72005-06-24 00:00:00 -0400527 /* Are there any arguments that must be processed? */
528
529 if (walk_state->arg_types) {
Bob Moore52fc0b02006-10-02 00:00:00 -0400530
Robert Moore73459f72005-06-24 00:00:00 -0400531 /* Get arguments */
532
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300533 status =
534 acpi_ps_get_arguments(walk_state, aml_op_start, op);
535 if (ACPI_FAILURE(status)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400536 status =
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300537 acpi_ps_complete_op(walk_state, &op,
538 status);
Len Brown4be44fc2005-08-05 00:44:28 -0400539 if (ACPI_FAILURE(status)) {
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300540 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400541 }
542
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300543 continue;
Robert Moore73459f72005-06-24 00:00:00 -0400544 }
545 }
546
547 /* Check for arguments that need to be processed */
548
Bob Moorea62a7112017-08-03 14:27:22 +0800549 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
Bob Moore1ef63232018-02-15 13:09:28 -0800550 "Parseloop: argument count: %8.8X\n",
Bob Moorea62a7112017-08-03 14:27:22 +0800551 walk_state->arg_count));
552
Robert Moore73459f72005-06-24 00:00:00 -0400553 if (walk_state->arg_count) {
554 /*
555 * There are arguments (complex ones), push Op and
556 * prepare for argument
557 */
Len Brown4be44fc2005-08-05 00:44:28 -0400558 status = acpi_ps_push_scope(parser_state, op,
559 walk_state->arg_types,
560 walk_state->arg_count);
561 if (ACPI_FAILURE(status)) {
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300562 status =
563 acpi_ps_complete_op(walk_state, &op,
564 status);
565 if (ACPI_FAILURE(status)) {
566 return_ACPI_STATUS(status);
567 }
568
569 continue;
Robert Moore73459f72005-06-24 00:00:00 -0400570 }
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300571
Robert Moore73459f72005-06-24 00:00:00 -0400572 op = NULL;
573 continue;
574 }
575
576 /*
577 * All arguments have been processed -- Op is complete,
578 * prepare for next
579 */
Len Brown4be44fc2005-08-05 00:44:28 -0400580 walk_state->op_info =
581 acpi_ps_get_opcode_info(op->common.aml_opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400582 if (walk_state->op_info->flags & AML_NAMED) {
Lin Ming941f48b2008-04-10 19:06:41 +0400583 if (op->common.aml_opcode == AML_REGION_OP ||
584 op->common.aml_opcode == AML_DATA_REGION_OP) {
Robert Moore73459f72005-06-24 00:00:00 -0400585 /*
586 * Skip parsing of control method or opregion body,
587 * because we don't have enough info in the first pass
588 * to parse them correctly.
589 *
590 * Completed parsing an op_region declaration, we now
591 * know the length.
592 */
Len Brown4be44fc2005-08-05 00:44:28 -0400593 op->named.length =
594 (u32) (parser_state->aml - op->named.data);
Robert Moore73459f72005-06-24 00:00:00 -0400595 }
596 }
597
598 if (walk_state->op_info->flags & AML_CREATE) {
599 /*
Bob Mooreba494be2012-07-12 09:40:10 +0800600 * Backup to beginning of create_XXXfield declaration (1 for
Robert Moore73459f72005-06-24 00:00:00 -0400601 * Opcode)
602 *
603 * body_length is unknown until we parse the body
604 */
Len Brown4be44fc2005-08-05 00:44:28 -0400605 op->named.length =
606 (u32) (parser_state->aml - op->named.data);
Robert Moore73459f72005-06-24 00:00:00 -0400607 }
608
Lin Mingef805d92008-04-10 19:06:41 +0400609 if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
610 /*
611 * Backup to beginning of bank_field declaration
612 *
613 * body_length is unknown until we parse the body
614 */
615 op->named.length =
616 (u32) (parser_state->aml - op->named.data);
617 }
618
Robert Moore73459f72005-06-24 00:00:00 -0400619 /* This op complete, notify the dispatcher */
620
621 if (walk_state->ascending_callback != NULL) {
Len Brown4be44fc2005-08-05 00:44:28 -0400622 walk_state->op = op;
Robert Moore73459f72005-06-24 00:00:00 -0400623 walk_state->opcode = op->common.aml_opcode;
624
Len Brown4be44fc2005-08-05 00:44:28 -0400625 status = walk_state->ascending_callback(walk_state);
626 status =
627 acpi_ps_next_parse_state(walk_state, op, status);
Robert Moore73459f72005-06-24 00:00:00 -0400628 if (status == AE_CTRL_PENDING) {
629 status = AE_OK;
Robert Moore73459f72005-06-24 00:00:00 -0400630 }
631 }
632
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300633 status = acpi_ps_complete_op(walk_state, &op, status);
634 if (ACPI_FAILURE(status)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400635 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400636 }
637
Len Brown4be44fc2005-08-05 00:44:28 -0400638 } /* while parser_state->Aml */
Robert Moore73459f72005-06-24 00:00:00 -0400639
Mikhail Kouzmich4d0b4af2007-02-02 19:48:21 +0300640 status = acpi_ps_complete_final_op(walk_state, op, status);
Len Brown4be44fc2005-08-05 00:44:28 -0400641 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400642}