blob: c66029b890b180ea87e188b7206073784fb165b3 [file] [log] [blame]
Robert Moore73459f72005-06-24 00:00:00 -04001/******************************************************************************
2 *
3 * Module Name: psloop - Main AML parse loop
4 *
5 *****************************************************************************/
6
7/*
Bob Moore4a90c7e2006-01-13 16:22:00 -05008 * Copyright (C) 2000 - 2006, R. Byron Moore
Robert Moore73459f72005-06-24 00:00:00 -04009 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
Robert Moore73459f72005-06-24 00:00:00 -040044/*
45 * Parse the AML and build an operation tree as most interpreters,
46 * like Perl, do. Parsing is done by hand rather than with a YACC
47 * generated parser to tightly constrain stack and dynamic memory
48 * usage. At the same time, parsing is kept flexible and the code
49 * fairly compact by parsing based on a list of AML opcode
50 * templates in aml_op_info[]
51 */
52
53#include <acpi/acpi.h>
54#include <acpi/acparser.h>
55#include <acpi/acdispat.h>
56#include <acpi/amlcode.h>
Robert Moore73459f72005-06-24 00:00:00 -040057
58#define _COMPONENT ACPI_PARSER
Len Brown4be44fc2005-08-05 00:44:28 -040059ACPI_MODULE_NAME("psloop")
Robert Moore73459f72005-06-24 00:00:00 -040060
Len Brown4be44fc2005-08-05 00:44:28 -040061static u32 acpi_gbl_depth = 0;
Robert Moore73459f72005-06-24 00:00:00 -040062
63/*******************************************************************************
64 *
65 * FUNCTION: acpi_ps_parse_loop
66 *
67 * PARAMETERS: walk_state - Current state
68 *
69 * RETURN: Status
70 *
71 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
72 * a tree of ops.
73 *
74 ******************************************************************************/
75
Len Brown4be44fc2005-08-05 00:44:28 -040076acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
Robert Moore73459f72005-06-24 00:00:00 -040077{
Len Brown4be44fc2005-08-05 00:44:28 -040078 acpi_status status = AE_OK;
79 acpi_status status2;
80 union acpi_parse_object *op = NULL; /* current op */
81 union acpi_parse_object *arg = NULL;
82 union acpi_parse_object *pre_op = NULL;
83 struct acpi_parse_state *parser_state;
84 u8 *aml_op_start = NULL;
Robert Moore73459f72005-06-24 00:00:00 -040085
Len Brown4be44fc2005-08-05 00:44:28 -040086 ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state);
Robert Moore73459f72005-06-24 00:00:00 -040087
88 if (walk_state->descending_callback == NULL) {
Len Brown4be44fc2005-08-05 00:44:28 -040089 return_ACPI_STATUS(AE_BAD_PARAMETER);
Robert Moore73459f72005-06-24 00:00:00 -040090 }
91
92 parser_state = &walk_state->parser_state;
93 walk_state->arg_types = 0;
94
95#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
96
97 if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
98 /* We are restarting a preempted control method */
99
Len Brown4be44fc2005-08-05 00:44:28 -0400100 if (acpi_ps_has_completed_scope(parser_state)) {
Robert Moore73459f72005-06-24 00:00:00 -0400101 /*
102 * We must check if a predicate to an IF or WHILE statement
103 * was just completed
104 */
105 if ((parser_state->scope->parse_scope.op) &&
Len Brown4be44fc2005-08-05 00:44:28 -0400106 ((parser_state->scope->parse_scope.op->common.
107 aml_opcode == AML_IF_OP)
108 || (parser_state->scope->parse_scope.op->common.
109 aml_opcode == AML_WHILE_OP))
110 && (walk_state->control_state)
111 && (walk_state->control_state->common.state ==
112 ACPI_CONTROL_PREDICATE_EXECUTING)) {
Robert Moore73459f72005-06-24 00:00:00 -0400113 /*
114 * A predicate was just completed, get the value of the
115 * predicate and branch based on that value
116 */
117 walk_state->op = NULL;
Len Brown4be44fc2005-08-05 00:44:28 -0400118 status =
119 acpi_ds_get_predicate_value(walk_state,
120 ACPI_TO_POINTER
121 (TRUE));
122 if (ACPI_FAILURE(status)
123 && ((status & AE_CODE_MASK) !=
124 AE_CODE_CONTROL)) {
Robert Moore73459f72005-06-24 00:00:00 -0400125 if (status == AE_AML_NO_RETURN_VALUE) {
Bob Moore4a90c7e2006-01-13 16:22:00 -0500126 ACPI_REPORT_ERROR(("Invoked method did not return a value, %s\n", acpi_format_exception(status)));
Robert Moore73459f72005-06-24 00:00:00 -0400127
128 }
Bob Moore4a90c7e2006-01-13 16:22:00 -0500129 ACPI_REPORT_ERROR(("get_predicate Failed, %s\n", acpi_format_exception(status)));
Len Brown4be44fc2005-08-05 00:44:28 -0400130 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400131 }
132
Len Brown4be44fc2005-08-05 00:44:28 -0400133 status =
134 acpi_ps_next_parse_state(walk_state, op,
135 status);
Robert Moore73459f72005-06-24 00:00:00 -0400136 }
137
Len Brown4be44fc2005-08-05 00:44:28 -0400138 acpi_ps_pop_scope(parser_state, &op,
139 &walk_state->arg_types,
140 &walk_state->arg_count);
141 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
142 "Popped scope, Op=%p\n", op));
143 } else if (walk_state->prev_op) {
Robert Moore73459f72005-06-24 00:00:00 -0400144 /* We were in the middle of an op */
145
146 op = walk_state->prev_op;
147 walk_state->arg_types = walk_state->prev_arg_types;
148 }
149 }
150#endif
151
152 /* Iterative parsing loop, while there is more AML to process: */
153
154 while ((parser_state->aml < parser_state->aml_end) || (op)) {
155 aml_op_start = parser_state->aml;
156 if (!op) {
157 /* Get the next opcode from the AML stream */
158
Len Brown4be44fc2005-08-05 00:44:28 -0400159 walk_state->aml_offset =
160 (u32) ACPI_PTR_DIFF(parser_state->aml,
161 parser_state->aml_start);
162 walk_state->opcode = acpi_ps_peek_opcode(parser_state);
Robert Moore73459f72005-06-24 00:00:00 -0400163
164 /*
165 * First cut to determine what we have found:
166 * 1) A valid AML opcode
167 * 2) A name string
168 * 3) An unknown/invalid opcode
169 */
Len Brown4be44fc2005-08-05 00:44:28 -0400170 walk_state->op_info =
171 acpi_ps_get_opcode_info(walk_state->opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400172 switch (walk_state->op_info->class) {
173 case AML_CLASS_ASCII:
174 case AML_CLASS_PREFIX:
175 /*
176 * Starts with a valid prefix or ASCII char, this is a name
177 * string. Convert the bare name string to a namepath.
178 */
179 walk_state->opcode = AML_INT_NAMEPATH_OP;
180 walk_state->arg_types = ARGP_NAMESTRING;
181 break;
182
183 case AML_CLASS_UNKNOWN:
184
185 /* The opcode is unrecognized. Just skip unknown opcodes */
186
Bob Moore4a90c7e2006-01-13 16:22:00 -0500187 ACPI_REPORT_ERROR(("Found unknown opcode %X at AML address %p offset %X, ignoring\n", walk_state->opcode, parser_state->aml, walk_state->aml_offset));
Robert Moore73459f72005-06-24 00:00:00 -0400188
Len Brown4be44fc2005-08-05 00:44:28 -0400189 ACPI_DUMP_BUFFER(parser_state->aml, 128);
Robert Moore73459f72005-06-24 00:00:00 -0400190
191 /* Assume one-byte bad opcode */
192
193 parser_state->aml++;
194 continue;
195
196 default:
197
198 /* Found opcode info, this is a normal opcode */
199
Len Brown4be44fc2005-08-05 00:44:28 -0400200 parser_state->aml +=
201 acpi_ps_get_opcode_size(walk_state->opcode);
202 walk_state->arg_types =
203 walk_state->op_info->parse_args;
Robert Moore73459f72005-06-24 00:00:00 -0400204 break;
205 }
206
207 /* Create Op structure and append to parent's argument list */
208
209 if (walk_state->op_info->flags & AML_NAMED) {
210 /* Allocate a new pre_op if necessary */
211
212 if (!pre_op) {
Len Brown4be44fc2005-08-05 00:44:28 -0400213 pre_op =
214 acpi_ps_alloc_op(walk_state->
215 opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400216 if (!pre_op) {
217 status = AE_NO_MEMORY;
218 goto close_this_op;
219 }
220 }
221
222 pre_op->common.value.arg = NULL;
223 pre_op->common.aml_opcode = walk_state->opcode;
224
225 /*
226 * Get and append arguments until we find the node that contains
227 * the name (the type ARGP_NAME).
228 */
Len Brown4be44fc2005-08-05 00:44:28 -0400229 while (GET_CURRENT_ARG_TYPE
230 (walk_state->arg_types)
231 &&
232 (GET_CURRENT_ARG_TYPE
233 (walk_state->arg_types) != ARGP_NAME)) {
234 status =
235 acpi_ps_get_next_arg(walk_state,
236 parser_state,
237 GET_CURRENT_ARG_TYPE
238 (walk_state->
239 arg_types),
240 &arg);
241 if (ACPI_FAILURE(status)) {
Robert Moore73459f72005-06-24 00:00:00 -0400242 goto close_this_op;
243 }
244
Len Brown4be44fc2005-08-05 00:44:28 -0400245 acpi_ps_append_arg(pre_op, arg);
246 INCREMENT_ARG_LIST(walk_state->
247 arg_types);
Robert Moore73459f72005-06-24 00:00:00 -0400248 }
249
250 /*
251 * Make sure that we found a NAME and didn't run out of
252 * arguments
253 */
Len Brown4be44fc2005-08-05 00:44:28 -0400254 if (!GET_CURRENT_ARG_TYPE
255 (walk_state->arg_types)) {
Robert Moore73459f72005-06-24 00:00:00 -0400256 status = AE_AML_NO_OPERAND;
257 goto close_this_op;
258 }
259
260 /* We know that this arg is a name, move to next arg */
261
Len Brown4be44fc2005-08-05 00:44:28 -0400262 INCREMENT_ARG_LIST(walk_state->arg_types);
Robert Moore73459f72005-06-24 00:00:00 -0400263
264 /*
265 * Find the object. This will either insert the object into
266 * the namespace or simply look it up
267 */
268 walk_state->op = NULL;
269
Len Brown4be44fc2005-08-05 00:44:28 -0400270 status =
271 walk_state->descending_callback(walk_state,
272 &op);
273 if (ACPI_FAILURE(status)) {
Bob Moore4a90c7e2006-01-13 16:22:00 -0500274 ACPI_REPORT_ERROR(("During name lookup/catalog, %s\n", acpi_format_exception(status)));
Robert Moore73459f72005-06-24 00:00:00 -0400275 goto close_this_op;
276 }
277
278 if (!op) {
279 continue;
280 }
281
Len Brown4be44fc2005-08-05 00:44:28 -0400282 status =
283 acpi_ps_next_parse_state(walk_state, op,
284 status);
Robert Moore73459f72005-06-24 00:00:00 -0400285 if (status == AE_CTRL_PENDING) {
286 status = AE_OK;
287 goto close_this_op;
288 }
289
Len Brown4be44fc2005-08-05 00:44:28 -0400290 if (ACPI_FAILURE(status)) {
Robert Moore73459f72005-06-24 00:00:00 -0400291 goto close_this_op;
292 }
293
Len Brown4be44fc2005-08-05 00:44:28 -0400294 acpi_ps_append_arg(op,
295 pre_op->common.value.arg);
Robert Moore73459f72005-06-24 00:00:00 -0400296 acpi_gbl_depth++;
297
298 if (op->common.aml_opcode == AML_REGION_OP) {
299 /*
300 * Defer final parsing of an operation_region body,
301 * because we don't have enough info in the first pass
302 * to parse it correctly (i.e., there may be method
303 * calls within the term_arg elements of the body.)
304 *
305 * However, we must continue parsing because
306 * the opregion is not a standalone package --
307 * we don't know where the end is at this point.
308 *
309 * (Length is unknown until parse of the body complete)
310 */
Len Brown4be44fc2005-08-05 00:44:28 -0400311 op->named.data = aml_op_start;
312 op->named.length = 0;
Robert Moore73459f72005-06-24 00:00:00 -0400313 }
Len Brown4be44fc2005-08-05 00:44:28 -0400314 } else {
Robert Moore73459f72005-06-24 00:00:00 -0400315 /* Not a named opcode, just allocate Op and append to parent */
316
Len Brown4be44fc2005-08-05 00:44:28 -0400317 walk_state->op_info =
318 acpi_ps_get_opcode_info(walk_state->opcode);
319 op = acpi_ps_alloc_op(walk_state->opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400320 if (!op) {
321 status = AE_NO_MEMORY;
322 goto close_this_op;
323 }
324
325 if (walk_state->op_info->flags & AML_CREATE) {
326 /*
327 * Backup to beginning of create_xXXfield declaration
328 * body_length is unknown until we parse the body
329 */
Len Brown4be44fc2005-08-05 00:44:28 -0400330 op->named.data = aml_op_start;
331 op->named.length = 0;
Robert Moore73459f72005-06-24 00:00:00 -0400332 }
333
Len Brown4be44fc2005-08-05 00:44:28 -0400334 acpi_ps_append_arg(acpi_ps_get_parent_scope
335 (parser_state), op);
Robert Moore73459f72005-06-24 00:00:00 -0400336
337 if ((walk_state->descending_callback != NULL)) {
338 /*
339 * Find the object. This will either insert the object into
340 * the namespace or simply look it up
341 */
342 walk_state->op = op;
343
Len Brown4be44fc2005-08-05 00:44:28 -0400344 status =
345 walk_state->
346 descending_callback(walk_state,
347 &op);
348 status =
349 acpi_ps_next_parse_state(walk_state,
350 op,
351 status);
Robert Moore73459f72005-06-24 00:00:00 -0400352 if (status == AE_CTRL_PENDING) {
353 status = AE_OK;
354 goto close_this_op;
355 }
356
Len Brown4be44fc2005-08-05 00:44:28 -0400357 if (ACPI_FAILURE(status)) {
Robert Moore73459f72005-06-24 00:00:00 -0400358 goto close_this_op;
359 }
360 }
361 }
362
363 op->common.aml_offset = walk_state->aml_offset;
364
365 if (walk_state->op_info) {
Len Brown4be44fc2005-08-05 00:44:28 -0400366 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
367 "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
368 (u32) op->common.aml_opcode,
369 walk_state->op_info->name, op,
370 parser_state->aml,
371 op->common.aml_offset));
Robert Moore73459f72005-06-24 00:00:00 -0400372 }
373 }
374
Robert Moore73459f72005-06-24 00:00:00 -0400375 /*
376 * Start arg_count at zero because we don't know if there are
377 * any args yet
378 */
379 walk_state->arg_count = 0;
380
381 /* Are there any arguments that must be processed? */
382
383 if (walk_state->arg_types) {
384 /* Get arguments */
385
386 switch (op->common.aml_opcode) {
Len Brown4be44fc2005-08-05 00:44:28 -0400387 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
388 case AML_WORD_OP: /* AML_WORDDATA_ARG */
389 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
390 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
391 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
Robert Moore73459f72005-06-24 00:00:00 -0400392
393 /* Fill in constant or string argument directly */
394
Len Brown4be44fc2005-08-05 00:44:28 -0400395 acpi_ps_get_next_simple_arg(parser_state,
396 GET_CURRENT_ARG_TYPE
397 (walk_state->
398 arg_types), op);
Robert Moore73459f72005-06-24 00:00:00 -0400399 break;
400
Len Brown4be44fc2005-08-05 00:44:28 -0400401 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
Robert Moore73459f72005-06-24 00:00:00 -0400402
Len Brown4be44fc2005-08-05 00:44:28 -0400403 status =
404 acpi_ps_get_next_namepath(walk_state,
405 parser_state, op,
406 1);
407 if (ACPI_FAILURE(status)) {
Robert Moore73459f72005-06-24 00:00:00 -0400408 goto close_this_op;
409 }
410
411 walk_state->arg_types = 0;
412 break;
413
414 default:
415 /*
416 * Op is not a constant or string, append each argument
417 * to the Op
418 */
Len Brown4be44fc2005-08-05 00:44:28 -0400419 while (GET_CURRENT_ARG_TYPE
420 (walk_state->arg_types)
421 && !walk_state->arg_count) {
Robert Moore73459f72005-06-24 00:00:00 -0400422 walk_state->aml_offset = (u32)
Len Brown4be44fc2005-08-05 00:44:28 -0400423 ACPI_PTR_DIFF(parser_state->aml,
424 parser_state->
425 aml_start);
Robert Moore73459f72005-06-24 00:00:00 -0400426
Len Brown4be44fc2005-08-05 00:44:28 -0400427 status =
428 acpi_ps_get_next_arg(walk_state,
429 parser_state,
430 GET_CURRENT_ARG_TYPE
431 (walk_state->
432 arg_types),
433 &arg);
434 if (ACPI_FAILURE(status)) {
Robert Moore73459f72005-06-24 00:00:00 -0400435 goto close_this_op;
436 }
437
438 if (arg) {
Len Brown4be44fc2005-08-05 00:44:28 -0400439 arg->common.aml_offset =
440 walk_state->aml_offset;
441 acpi_ps_append_arg(op, arg);
Robert Moore73459f72005-06-24 00:00:00 -0400442 }
Len Brown4be44fc2005-08-05 00:44:28 -0400443 INCREMENT_ARG_LIST(walk_state->
444 arg_types);
Robert Moore73459f72005-06-24 00:00:00 -0400445 }
446
447 /* Special processing for certain opcodes */
448
Len Brown4be44fc2005-08-05 00:44:28 -0400449 /* TBD (remove): Temporary mechanism to disable this code if needed */
Robert Mooref9f46012005-07-08 00:00:00 -0400450
Robert Moore0c9938c2005-07-29 15:15:00 -0700451#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
Robert Mooref9f46012005-07-08 00:00:00 -0400452
Len Brown4be44fc2005-08-05 00:44:28 -0400453 if ((walk_state->pass_number <=
454 ACPI_IMODE_LOAD_PASS1)
455 &&
456 ((walk_state->
457 parse_flags & ACPI_PARSE_DISASSEMBLE) ==
458 0)) {
Robert Moore73459f72005-06-24 00:00:00 -0400459 /*
460 * We want to skip If/Else/While constructs during Pass1
461 * because we want to actually conditionally execute the
462 * code during Pass2.
463 *
464 * Except for disassembly, where we always want to
465 * walk the If/Else/While packages
466 */
467 switch (op->common.aml_opcode) {
468 case AML_IF_OP:
469 case AML_ELSE_OP:
470 case AML_WHILE_OP:
471
Len Brown4be44fc2005-08-05 00:44:28 -0400472 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
473 "Pass1: Skipping an If/Else/While body\n"));
Robert Moore0c9938c2005-07-29 15:15:00 -0700474
Robert Moore73459f72005-06-24 00:00:00 -0400475 /* Skip body of if/else/while in pass 1 */
476
Len Brown4be44fc2005-08-05 00:44:28 -0400477 parser_state->aml =
478 parser_state->pkg_end;
Robert Moore73459f72005-06-24 00:00:00 -0400479 walk_state->arg_count = 0;
480 break;
481
482 default:
483 break;
484 }
485 }
Robert Mooref9f46012005-07-08 00:00:00 -0400486#endif
Robert Moore73459f72005-06-24 00:00:00 -0400487 switch (op->common.aml_opcode) {
488 case AML_METHOD_OP:
489
490 /*
491 * Skip parsing of control method
492 * because we don't have enough info in the first pass
493 * to parse it correctly.
494 *
495 * Save the length and address of the body
496 */
Len Brown4be44fc2005-08-05 00:44:28 -0400497 op->named.data = parser_state->aml;
498 op->named.length =
499 (u32) (parser_state->pkg_end -
500 parser_state->aml);
Robert Moore73459f72005-06-24 00:00:00 -0400501
502 /* Skip body of method */
503
Len Brown4be44fc2005-08-05 00:44:28 -0400504 parser_state->aml =
505 parser_state->pkg_end;
Robert Moore73459f72005-06-24 00:00:00 -0400506 walk_state->arg_count = 0;
507 break;
508
509 case AML_BUFFER_OP:
510 case AML_PACKAGE_OP:
511 case AML_VAR_PACKAGE_OP:
512
513 if ((op->common.parent) &&
Len Brown4be44fc2005-08-05 00:44:28 -0400514 (op->common.parent->common.
515 aml_opcode == AML_NAME_OP)
516 && (walk_state->pass_number <=
517 ACPI_IMODE_LOAD_PASS2)) {
Robert Moore73459f72005-06-24 00:00:00 -0400518 /*
519 * Skip parsing of Buffers and Packages
520 * because we don't have enough info in the first pass
521 * to parse them correctly.
522 */
Len Brown4be44fc2005-08-05 00:44:28 -0400523 op->named.data = aml_op_start;
524 op->named.length =
525 (u32) (parser_state->
526 pkg_end -
527 aml_op_start);
Robert Moore73459f72005-06-24 00:00:00 -0400528
529 /* Skip body */
530
Len Brown4be44fc2005-08-05 00:44:28 -0400531 parser_state->aml =
532 parser_state->pkg_end;
Robert Moore73459f72005-06-24 00:00:00 -0400533 walk_state->arg_count = 0;
534 }
535 break;
536
537 case AML_WHILE_OP:
538
539 if (walk_state->control_state) {
Len Brown4be44fc2005-08-05 00:44:28 -0400540 walk_state->control_state->
541 control.package_end =
542 parser_state->pkg_end;
Robert Moore73459f72005-06-24 00:00:00 -0400543 }
544 break;
545
546 default:
547
548 /* No action for all other opcodes */
549 break;
550 }
551 break;
552 }
553 }
554
555 /* Check for arguments that need to be processed */
556
557 if (walk_state->arg_count) {
558 /*
559 * There are arguments (complex ones), push Op and
560 * prepare for argument
561 */
Len Brown4be44fc2005-08-05 00:44:28 -0400562 status = acpi_ps_push_scope(parser_state, op,
563 walk_state->arg_types,
564 walk_state->arg_count);
565 if (ACPI_FAILURE(status)) {
Robert Moore73459f72005-06-24 00:00:00 -0400566 goto close_this_op;
567 }
568 op = NULL;
569 continue;
570 }
571
572 /*
573 * All arguments have been processed -- Op is complete,
574 * prepare for next
575 */
Len Brown4be44fc2005-08-05 00:44:28 -0400576 walk_state->op_info =
577 acpi_ps_get_opcode_info(op->common.aml_opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400578 if (walk_state->op_info->flags & AML_NAMED) {
579 if (acpi_gbl_depth) {
580 acpi_gbl_depth--;
581 }
582
583 if (op->common.aml_opcode == AML_REGION_OP) {
584 /*
585 * Skip parsing of control method or opregion body,
586 * because we don't have enough info in the first pass
587 * to parse them correctly.
588 *
589 * Completed parsing an op_region declaration, we now
590 * know the length.
591 */
Len Brown4be44fc2005-08-05 00:44:28 -0400592 op->named.length =
593 (u32) (parser_state->aml - op->named.data);
Robert Moore73459f72005-06-24 00:00:00 -0400594 }
595 }
596
597 if (walk_state->op_info->flags & AML_CREATE) {
598 /*
599 * Backup to beginning of create_xXXfield declaration (1 for
600 * Opcode)
601 *
602 * body_length is unknown until we parse the body
603 */
Len Brown4be44fc2005-08-05 00:44:28 -0400604 op->named.length =
605 (u32) (parser_state->aml - op->named.data);
Robert Moore73459f72005-06-24 00:00:00 -0400606 }
607
608 /* This op complete, notify the dispatcher */
609
610 if (walk_state->ascending_callback != NULL) {
Len Brown4be44fc2005-08-05 00:44:28 -0400611 walk_state->op = op;
Robert Moore73459f72005-06-24 00:00:00 -0400612 walk_state->opcode = op->common.aml_opcode;
613
Len Brown4be44fc2005-08-05 00:44:28 -0400614 status = walk_state->ascending_callback(walk_state);
615 status =
616 acpi_ps_next_parse_state(walk_state, op, status);
Robert Moore73459f72005-06-24 00:00:00 -0400617 if (status == AE_CTRL_PENDING) {
618 status = AE_OK;
619 goto close_this_op;
620 }
621 }
622
Len Brown4be44fc2005-08-05 00:44:28 -0400623 close_this_op:
Robert Moore73459f72005-06-24 00:00:00 -0400624 /*
625 * Finished one argument of the containing scope
626 */
627 parser_state->scope->parse_scope.arg_count--;
628
629 /* Finished with pre_op */
630
631 if (pre_op) {
Len Brown4be44fc2005-08-05 00:44:28 -0400632 acpi_ps_free_op(pre_op);
Robert Moore73459f72005-06-24 00:00:00 -0400633 pre_op = NULL;
634 }
635
636 /* Close this Op (will result in parse subtree deletion) */
637
Len Brown4be44fc2005-08-05 00:44:28 -0400638 status2 = acpi_ps_complete_this_op(walk_state, op);
639 if (ACPI_FAILURE(status2)) {
640 return_ACPI_STATUS(status2);
Robert Moore73459f72005-06-24 00:00:00 -0400641 }
642 op = NULL;
643
644 switch (status) {
645 case AE_OK:
646 break;
647
Robert Moore73459f72005-06-24 00:00:00 -0400648 case AE_CTRL_TRANSFER:
649
650 /* We are about to transfer to a called method. */
651
652 walk_state->prev_op = op;
653 walk_state->prev_arg_types = walk_state->arg_types;
Len Brown4be44fc2005-08-05 00:44:28 -0400654 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400655
656 case AE_CTRL_END:
657
Len Brown4be44fc2005-08-05 00:44:28 -0400658 acpi_ps_pop_scope(parser_state, &op,
659 &walk_state->arg_types,
660 &walk_state->arg_count);
Robert Moore73459f72005-06-24 00:00:00 -0400661
662 if (op) {
Len Brown4be44fc2005-08-05 00:44:28 -0400663 walk_state->op = op;
664 walk_state->op_info =
665 acpi_ps_get_opcode_info(op->common.
666 aml_opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400667 walk_state->opcode = op->common.aml_opcode;
668
Len Brown4be44fc2005-08-05 00:44:28 -0400669 status =
670 walk_state->ascending_callback(walk_state);
671 status =
672 acpi_ps_next_parse_state(walk_state, op,
673 status);
Robert Moore73459f72005-06-24 00:00:00 -0400674
Len Brown4be44fc2005-08-05 00:44:28 -0400675 status2 =
676 acpi_ps_complete_this_op(walk_state, op);
677 if (ACPI_FAILURE(status2)) {
678 return_ACPI_STATUS(status2);
Robert Moore73459f72005-06-24 00:00:00 -0400679 }
680 op = NULL;
681 }
682 status = AE_OK;
683 break;
684
Robert Moore73459f72005-06-24 00:00:00 -0400685 case AE_CTRL_BREAK:
686 case AE_CTRL_CONTINUE:
687
688 /* Pop off scopes until we find the While */
689
690 while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
Len Brown4be44fc2005-08-05 00:44:28 -0400691 acpi_ps_pop_scope(parser_state, &op,
692 &walk_state->arg_types,
693 &walk_state->arg_count);
Bob Mooredefba1d2005-12-16 17:05:00 -0500694
695 if (op->common.aml_opcode != AML_WHILE_OP) {
696 status2 =
697 acpi_ds_result_stack_pop
698 (walk_state);
699 if (ACPI_FAILURE(status2)) {
700 return_ACPI_STATUS(status2);
701 }
702 }
Robert Moore73459f72005-06-24 00:00:00 -0400703 }
704
705 /* Close this iteration of the While loop */
706
Len Brown4be44fc2005-08-05 00:44:28 -0400707 walk_state->op = op;
708 walk_state->op_info =
709 acpi_ps_get_opcode_info(op->common.aml_opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400710 walk_state->opcode = op->common.aml_opcode;
711
Len Brown4be44fc2005-08-05 00:44:28 -0400712 status = walk_state->ascending_callback(walk_state);
713 status =
714 acpi_ps_next_parse_state(walk_state, op, status);
Robert Moore73459f72005-06-24 00:00:00 -0400715
Len Brown4be44fc2005-08-05 00:44:28 -0400716 status2 = acpi_ps_complete_this_op(walk_state, op);
717 if (ACPI_FAILURE(status2)) {
718 return_ACPI_STATUS(status2);
Robert Moore73459f72005-06-24 00:00:00 -0400719 }
720 op = NULL;
721
722 status = AE_OK;
723 break;
724
Robert Moore73459f72005-06-24 00:00:00 -0400725 case AE_CTRL_TERMINATE:
726
727 status = AE_OK;
728
729 /* Clean up */
730 do {
731 if (op) {
Len Brown4be44fc2005-08-05 00:44:28 -0400732 status2 =
733 acpi_ps_complete_this_op(walk_state,
734 op);
735 if (ACPI_FAILURE(status2)) {
736 return_ACPI_STATUS(status2);
Robert Moore73459f72005-06-24 00:00:00 -0400737 }
738 }
Len Brown4be44fc2005-08-05 00:44:28 -0400739 acpi_ps_pop_scope(parser_state, &op,
740 &walk_state->arg_types,
741 &walk_state->arg_count);
Robert Moore73459f72005-06-24 00:00:00 -0400742
743 } while (op);
744
Len Brown4be44fc2005-08-05 00:44:28 -0400745 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400746
Len Brown4be44fc2005-08-05 00:44:28 -0400747 default: /* All other non-AE_OK status */
Robert Moore73459f72005-06-24 00:00:00 -0400748
749 do {
750 if (op) {
Len Brown4be44fc2005-08-05 00:44:28 -0400751 status2 =
752 acpi_ps_complete_this_op(walk_state,
753 op);
754 if (ACPI_FAILURE(status2)) {
755 return_ACPI_STATUS(status2);
Robert Moore73459f72005-06-24 00:00:00 -0400756 }
757 }
Len Brown4be44fc2005-08-05 00:44:28 -0400758 acpi_ps_pop_scope(parser_state, &op,
759 &walk_state->arg_types,
760 &walk_state->arg_count);
Robert Moore73459f72005-06-24 00:00:00 -0400761
762 } while (op);
763
Robert Moore73459f72005-06-24 00:00:00 -0400764 /*
765 * TBD: Cleanup parse ops on error
766 */
767#if 0
768 if (op == NULL) {
Len Brown4be44fc2005-08-05 00:44:28 -0400769 acpi_ps_pop_scope(parser_state, &op,
770 &walk_state->arg_types,
771 &walk_state->arg_count);
Robert Moore73459f72005-06-24 00:00:00 -0400772 }
773#endif
774 walk_state->prev_op = op;
775 walk_state->prev_arg_types = walk_state->arg_types;
Len Brown4be44fc2005-08-05 00:44:28 -0400776 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400777 }
778
779 /* This scope complete? */
780
Len Brown4be44fc2005-08-05 00:44:28 -0400781 if (acpi_ps_has_completed_scope(parser_state)) {
782 acpi_ps_pop_scope(parser_state, &op,
783 &walk_state->arg_types,
784 &walk_state->arg_count);
785 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
786 "Popped scope, Op=%p\n", op));
787 } else {
Robert Moore73459f72005-06-24 00:00:00 -0400788 op = NULL;
789 }
790
Len Brown4be44fc2005-08-05 00:44:28 -0400791 } /* while parser_state->Aml */
Robert Moore73459f72005-06-24 00:00:00 -0400792
793 /*
794 * Complete the last Op (if not completed), and clear the scope stack.
795 * It is easily possible to end an AML "package" with an unbounded number
796 * of open scopes (such as when several ASL blocks are closed with
797 * sequential closing braces). We want to terminate each one cleanly.
798 */
Len Brown4be44fc2005-08-05 00:44:28 -0400799 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n",
800 op));
Robert Moore73459f72005-06-24 00:00:00 -0400801 do {
802 if (op) {
803 if (walk_state->ascending_callback != NULL) {
Len Brown4be44fc2005-08-05 00:44:28 -0400804 walk_state->op = op;
805 walk_state->op_info =
806 acpi_ps_get_opcode_info(op->common.
807 aml_opcode);
Robert Moore73459f72005-06-24 00:00:00 -0400808 walk_state->opcode = op->common.aml_opcode;
809
Len Brown4be44fc2005-08-05 00:44:28 -0400810 status =
811 walk_state->ascending_callback(walk_state);
812 status =
813 acpi_ps_next_parse_state(walk_state, op,
814 status);
Robert Moore73459f72005-06-24 00:00:00 -0400815 if (status == AE_CTRL_PENDING) {
816 status = AE_OK;
817 goto close_this_op;
818 }
819
820 if (status == AE_CTRL_TERMINATE) {
821 status = AE_OK;
822
823 /* Clean up */
824 do {
825 if (op) {
Len Brown4be44fc2005-08-05 00:44:28 -0400826 status2 =
827 acpi_ps_complete_this_op
828 (walk_state, op);
829 if (ACPI_FAILURE
830 (status2)) {
831 return_ACPI_STATUS
832 (status2);
Robert Moore73459f72005-06-24 00:00:00 -0400833 }
834 }
835
Len Brown4be44fc2005-08-05 00:44:28 -0400836 acpi_ps_pop_scope(parser_state,
837 &op,
838 &walk_state->
839 arg_types,
840 &walk_state->
841 arg_count);
Robert Moore73459f72005-06-24 00:00:00 -0400842
843 } while (op);
844
Len Brown4be44fc2005-08-05 00:44:28 -0400845 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400846 }
847
Len Brown4be44fc2005-08-05 00:44:28 -0400848 else if (ACPI_FAILURE(status)) {
Robert Moore73459f72005-06-24 00:00:00 -0400849 /* First error is most important */
850
Len Brown4be44fc2005-08-05 00:44:28 -0400851 (void)
852 acpi_ps_complete_this_op(walk_state,
853 op);
854 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400855 }
856 }
857
Len Brown4be44fc2005-08-05 00:44:28 -0400858 status2 = acpi_ps_complete_this_op(walk_state, op);
859 if (ACPI_FAILURE(status2)) {
860 return_ACPI_STATUS(status2);
Robert Moore73459f72005-06-24 00:00:00 -0400861 }
862 }
863
Len Brown4be44fc2005-08-05 00:44:28 -0400864 acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types,
865 &walk_state->arg_count);
Robert Moore73459f72005-06-24 00:00:00 -0400866
867 } while (op);
868
Len Brown4be44fc2005-08-05 00:44:28 -0400869 return_ACPI_STATUS(status);
Robert Moore73459f72005-06-24 00:00:00 -0400870}