aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/parser/psloop.c
diff options
context:
space:
mode:
authorRobert Moore <robert.moore@intel.com>2005-06-24 00:00:00 -0400
committerLen Brown <len.brown@intel.com>2005-07-13 23:45:36 -0400
commit73459f73e5d1602c59ebec114fc45185521353c1 (patch)
tree56c2183e345784d2be09c2f5d2530cf36221c55e /drivers/acpi/parser/psloop.c
parent88ac00f5a841dcfc5c682000f4a6add0add8caac (diff)
ACPICA 20050617-0624 from Bob Moore <robert.moore@intel.com>
ACPICA 20050617: Moved the object cache operations into the OS interface layer (OSL) to allow the host OS to handle these operations if desired (for example, the Linux OSL will invoke the slab allocator). This support is optional; the compile time define ACPI_USE_LOCAL_CACHE may be used to utilize the original cache code in the ACPI CA core. The new OSL interfaces are shown below. See utalloc.c for an example implementation, and acpiosxf.h for the exact interface definitions. Thanks to Alexey Starikovskiy. acpi_os_create_cache acpi_os_delete_cache acpi_os_purge_cache acpi_os_acquire_object acpi_os_release_object Modified the interfaces to acpi_os_acquire_lock and acpi_os_release_lock to return and restore a flags parameter. This fits better with many OS lock models. Note: the current execution state (interrupt handler or not) is no longer passed to these interfaces. If necessary, the OSL must determine this state by itself, a simple and fast operation. Thanks to Alexey Starikovskiy. Fixed a problem in the ACPI table handling where a valid XSDT was assumed present if the revision of the RSDP was 2 or greater. According to the ACPI specification, the XSDT is optional in all cases, and the table manager therefore now checks for both an RSDP >=2 and a valid XSDT pointer. Otherwise, the RSDT pointer is used. Some ACPI 2.0 compliant BIOSs contain only the RSDT. Fixed an interpreter problem with the Mid() operator in the case of an input string where the resulting output string is of zero length. It now correctly returns a valid, null terminated string object instead of a string object with a null pointer. Fixed a problem with the control method argument handling to allow a store to an Arg object that already contains an object of type Device. The Device object is now correctly overwritten. Previously, an error was returned. ACPICA 20050624: Modified the new OSL cache interfaces to use ACPI_CACHE_T as the type for the host-defined cache object. This allows the OSL implementation to define and type this object in any manner desired, simplifying the OSL implementation. For example, ACPI_CACHE_T is defined as kmem_cache_t for Linux, and should be defined in the OS-specific header file for other operating systems as required. Changed the interface to AcpiOsAcquireObject to directly return the requested object as the function return (instead of ACPI_STATUS.) This change was made for performance reasons, since this is the purpose of the interface in the first place. acpi_os_acquire_object is now similar to the acpi_os_allocate interface. Thanks to Alexey Starikovskiy. Modified the initialization sequence in acpi_initialize_subsystem to call the OSL interface acpi_osl_initialize first, before any local initialization. This change was required because the global initialization now calls OSL interfaces. Restructured the code base to split some files because of size and/or because the code logically belonged in a separate file. New files are listed below. utilities/utcache.c /* Local cache interfaces */ utilities/utmutex.c /* Local mutex support */ utilities/utstate.c /* State object support */ parser/psloop.c /* Main AML parse loop */ Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/parser/psloop.c')
-rw-r--r--drivers/acpi/parser/psloop.c775
1 files changed, 775 insertions, 0 deletions
diff --git a/drivers/acpi/parser/psloop.c b/drivers/acpi/parser/psloop.c
new file mode 100644
index 000000000000..decb2e9a049d
--- /dev/null
+++ b/drivers/acpi/parser/psloop.c
@@ -0,0 +1,775 @@
1/******************************************************************************
2 *
3 * Module Name: psloop - Main AML parse loop
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * 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
44
45/*
46 * Parse the AML and build an operation tree as most interpreters,
47 * like Perl, do. Parsing is done by hand rather than with a YACC
48 * generated parser to tightly constrain stack and dynamic memory
49 * usage. At the same time, parsing is kept flexible and the code
50 * fairly compact by parsing based on a list of AML opcode
51 * templates in aml_op_info[]
52 */
53
54#include <acpi/acpi.h>
55#include <acpi/acparser.h>
56#include <acpi/acdispat.h>
57#include <acpi/amlcode.h>
58#include <acpi/acnamesp.h>
59#include <acpi/acinterp.h>
60
61#define _COMPONENT ACPI_PARSER
62 ACPI_MODULE_NAME ("psloop")
63
64static u32 acpi_gbl_depth = 0;
65
66
67/*******************************************************************************
68 *
69 * FUNCTION: acpi_ps_parse_loop
70 *
71 * PARAMETERS: walk_state - Current state
72 *
73 * RETURN: Status
74 *
75 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
76 * a tree of ops.
77 *
78 ******************************************************************************/
79
80acpi_status
81acpi_ps_parse_loop (
82 struct acpi_walk_state *walk_state)
83{
84 acpi_status status = AE_OK;
85 acpi_status status2;
86 union acpi_parse_object *op = NULL; /* current op */
87 union acpi_parse_object *arg = NULL;
88 union acpi_parse_object *pre_op = NULL;
89 struct acpi_parse_state *parser_state;
90 u8 *aml_op_start = NULL;
91
92
93 ACPI_FUNCTION_TRACE_PTR ("ps_parse_loop", walk_state);
94
95 if (walk_state->descending_callback == NULL) {
96 return_ACPI_STATUS (AE_BAD_PARAMETER);
97 }
98
99 parser_state = &walk_state->parser_state;
100 walk_state->arg_types = 0;
101
102#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
103
104 if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
105 /* We are restarting a preempted control method */
106
107 if (acpi_ps_has_completed_scope (parser_state)) {
108 /*
109 * We must check if a predicate to an IF or WHILE statement
110 * was just completed
111 */
112 if ((parser_state->scope->parse_scope.op) &&
113 ((parser_state->scope->parse_scope.op->common.aml_opcode == AML_IF_OP) ||
114 (parser_state->scope->parse_scope.op->common.aml_opcode == AML_WHILE_OP)) &&
115 (walk_state->control_state) &&
116 (walk_state->control_state->common.state ==
117 ACPI_CONTROL_PREDICATE_EXECUTING)) {
118 /*
119 * A predicate was just completed, get the value of the
120 * predicate and branch based on that value
121 */
122 walk_state->op = NULL;
123 status = acpi_ds_get_predicate_value (walk_state, ACPI_TO_POINTER (TRUE));
124 if (ACPI_FAILURE (status) &&
125 ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) {
126 if (status == AE_AML_NO_RETURN_VALUE) {
127 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
128 "Invoked method did not return a value, %s\n",
129 acpi_format_exception (status)));
130
131 }
132 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
133 "get_predicate Failed, %s\n",
134 acpi_format_exception (status)));
135 return_ACPI_STATUS (status);
136 }
137
138 status = acpi_ps_next_parse_state (walk_state, op, status);
139 }
140
141 acpi_ps_pop_scope (parser_state, &op,
142 &walk_state->arg_types, &walk_state->arg_count);
143 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
144 }
145 else if (walk_state->prev_op) {
146 /* We were in the middle of an op */
147
148 op = walk_state->prev_op;
149 walk_state->arg_types = walk_state->prev_arg_types;
150 }
151 }
152#endif
153
154 /* Iterative parsing loop, while there is more AML to process: */
155
156 while ((parser_state->aml < parser_state->aml_end) || (op)) {
157 aml_op_start = parser_state->aml;
158 if (!op) {
159 /* Get the next opcode from the AML stream */
160
161 walk_state->aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml,
162 parser_state->aml_start);
163 walk_state->opcode = acpi_ps_peek_opcode (parser_state);
164
165 /*
166 * First cut to determine what we have found:
167 * 1) A valid AML opcode
168 * 2) A name string
169 * 3) An unknown/invalid opcode
170 */
171 walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
172 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
187 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
188 "Found unknown opcode %X at AML address %p offset %X, ignoring\n",
189 walk_state->opcode, parser_state->aml, walk_state->aml_offset));
190
191 ACPI_DUMP_BUFFER (parser_state->aml, 128);
192
193 /* Assume one-byte bad opcode */
194
195 parser_state->aml++;
196 continue;
197
198 default:
199
200 /* Found opcode info, this is a normal opcode */
201
202 parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode);
203 walk_state->arg_types = walk_state->op_info->parse_args;
204 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) {
213 pre_op = acpi_ps_alloc_op (walk_state->opcode);
214 if (!pre_op) {
215 status = AE_NO_MEMORY;
216 goto close_this_op;
217 }
218 }
219
220 pre_op->common.value.arg = NULL;
221 pre_op->common.aml_opcode = walk_state->opcode;
222
223 /*
224 * Get and append arguments until we find the node that contains
225 * the name (the type ARGP_NAME).
226 */
227 while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
228 (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) {
229 status = acpi_ps_get_next_arg (walk_state, parser_state,
230 GET_CURRENT_ARG_TYPE (walk_state->arg_types), &arg);
231 if (ACPI_FAILURE (status)) {
232 goto close_this_op;
233 }
234
235 acpi_ps_append_arg (pre_op, arg);
236 INCREMENT_ARG_LIST (walk_state->arg_types);
237 }
238
239 /*
240 * Make sure that we found a NAME and didn't run out of
241 * arguments
242 */
243 if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) {
244 status = AE_AML_NO_OPERAND;
245 goto close_this_op;
246 }
247
248 /* We know that this arg is a name, move to next arg */
249
250 INCREMENT_ARG_LIST (walk_state->arg_types);
251
252 /*
253 * Find the object. This will either insert the object into
254 * the namespace or simply look it up
255 */
256 walk_state->op = NULL;
257
258 status = walk_state->descending_callback (walk_state, &op);
259 if (ACPI_FAILURE (status)) {
260 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
261 "During name lookup/catalog, %s\n",
262 acpi_format_exception (status)));
263 goto close_this_op;
264 }
265
266 if (!op) {
267 continue;
268 }
269
270 status = acpi_ps_next_parse_state (walk_state, op, status);
271 if (status == AE_CTRL_PENDING) {
272 status = AE_OK;
273 goto close_this_op;
274 }
275
276 if (ACPI_FAILURE (status)) {
277 goto close_this_op;
278 }
279
280 acpi_ps_append_arg (op, pre_op->common.value.arg);
281 acpi_gbl_depth++;
282
283 if (op->common.aml_opcode == AML_REGION_OP) {
284 /*
285 * Defer final parsing of an operation_region body,
286 * because we don't have enough info in the first pass
287 * to parse it correctly (i.e., there may be method
288 * calls within the term_arg elements of the body.)
289 *
290 * However, we must continue parsing because
291 * the opregion is not a standalone package --
292 * we don't know where the end is at this point.
293 *
294 * (Length is unknown until parse of the body complete)
295 */
296 op->named.data = aml_op_start;
297 op->named.length = 0;
298 }
299 }
300 else {
301 /* Not a named opcode, just allocate Op and append to parent */
302
303 walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);
304 op = acpi_ps_alloc_op (walk_state->opcode);
305 if (!op) {
306 status = AE_NO_MEMORY;
307 goto close_this_op;
308 }
309
310 if (walk_state->op_info->flags & AML_CREATE) {
311 /*
312 * Backup to beginning of create_xXXfield declaration
313 * body_length is unknown until we parse the body
314 */
315 op->named.data = aml_op_start;
316 op->named.length = 0;
317 }
318
319 acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);
320
321 if ((walk_state->descending_callback != NULL)) {
322 /*
323 * Find the object. This will either insert the object into
324 * the namespace or simply look it up
325 */
326 walk_state->op = op;
327
328 status = walk_state->descending_callback (walk_state, &op);
329 status = acpi_ps_next_parse_state (walk_state, op, status);
330 if (status == AE_CTRL_PENDING) {
331 status = AE_OK;
332 goto close_this_op;
333 }
334
335 if (ACPI_FAILURE (status)) {
336 goto close_this_op;
337 }
338 }
339 }
340
341 op->common.aml_offset = walk_state->aml_offset;
342
343 if (walk_state->op_info) {
344 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
345 "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n",
346 (u32) op->common.aml_opcode, walk_state->op_info->name,
347 op, parser_state->aml, op->common.aml_offset));
348 }
349 }
350
351
352 /*
353 * Start arg_count at zero because we don't know if there are
354 * any args yet
355 */
356 walk_state->arg_count = 0;
357
358 /* Are there any arguments that must be processed? */
359
360 if (walk_state->arg_types) {
361 /* Get arguments */
362
363 switch (op->common.aml_opcode) {
364 case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
365 case AML_WORD_OP: /* AML_WORDDATA_ARG */
366 case AML_DWORD_OP: /* AML_DWORDATA_ARG */
367 case AML_QWORD_OP: /* AML_QWORDATA_ARG */
368 case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
369
370 /* Fill in constant or string argument directly */
371
372 acpi_ps_get_next_simple_arg (parser_state,
373 GET_CURRENT_ARG_TYPE (walk_state->arg_types), op);
374 break;
375
376 case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
377
378 status = acpi_ps_get_next_namepath (walk_state, parser_state, op, 1);
379 if (ACPI_FAILURE (status)) {
380 goto close_this_op;
381 }
382
383 walk_state->arg_types = 0;
384 break;
385
386 default:
387 /*
388 * Op is not a constant or string, append each argument
389 * to the Op
390 */
391 while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) &&
392 !walk_state->arg_count) {
393 walk_state->aml_offset = (u32)
394 ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start);
395
396 status = acpi_ps_get_next_arg (walk_state, parser_state,
397 GET_CURRENT_ARG_TYPE (walk_state->arg_types),
398 &arg);
399 if (ACPI_FAILURE (status)) {
400 goto close_this_op;
401 }
402
403 if (arg) {
404 arg->common.aml_offset = walk_state->aml_offset;
405 acpi_ps_append_arg (op, arg);
406 }
407 INCREMENT_ARG_LIST (walk_state->arg_types);
408 }
409
410 /* Special processing for certain opcodes */
411
412 if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) &&
413 ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
414 /*
415 * We want to skip If/Else/While constructs during Pass1
416 * because we want to actually conditionally execute the
417 * code during Pass2.
418 *
419 * Except for disassembly, where we always want to
420 * walk the If/Else/While packages
421 */
422 switch (op->common.aml_opcode) {
423 case AML_IF_OP:
424 case AML_ELSE_OP:
425 case AML_WHILE_OP:
426
427 /* Skip body of if/else/while in pass 1 */
428
429 parser_state->aml = parser_state->pkg_end;
430 walk_state->arg_count = 0;
431 break;
432
433 default:
434 break;
435 }
436 }
437
438 switch (op->common.aml_opcode) {
439 case AML_METHOD_OP:
440
441 /*
442 * Skip parsing of control method
443 * because we don't have enough info in the first pass
444 * to parse it correctly.
445 *
446 * Save the length and address of the body
447 */
448 op->named.data = parser_state->aml;
449 op->named.length = (u32) (parser_state->pkg_end -
450 parser_state->aml);
451
452 /* Skip body of method */
453
454 parser_state->aml = parser_state->pkg_end;
455 walk_state->arg_count = 0;
456 break;
457
458 case AML_BUFFER_OP:
459 case AML_PACKAGE_OP:
460 case AML_VAR_PACKAGE_OP:
461
462 if ((op->common.parent) &&
463 (op->common.parent->common.aml_opcode == AML_NAME_OP) &&
464 (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) {
465 /*
466 * Skip parsing of Buffers and Packages
467 * because we don't have enough info in the first pass
468 * to parse them correctly.
469 */
470 op->named.data = aml_op_start;
471 op->named.length = (u32) (parser_state->pkg_end -
472 aml_op_start);
473
474 /* Skip body */
475
476 parser_state->aml = parser_state->pkg_end;
477 walk_state->arg_count = 0;
478 }
479 break;
480
481 case AML_WHILE_OP:
482
483 if (walk_state->control_state) {
484 walk_state->control_state->control.package_end =
485 parser_state->pkg_end;
486 }
487 break;
488
489 default:
490
491 /* No action for all other opcodes */
492 break;
493 }
494 break;
495 }
496 }
497
498 /* Check for arguments that need to be processed */
499
500 if (walk_state->arg_count) {
501 /*
502 * There are arguments (complex ones), push Op and
503 * prepare for argument
504 */
505 status = acpi_ps_push_scope (parser_state, op,
506 walk_state->arg_types, walk_state->arg_count);
507 if (ACPI_FAILURE (status)) {
508 goto close_this_op;
509 }
510 op = NULL;
511 continue;
512 }
513
514 /*
515 * All arguments have been processed -- Op is complete,
516 * prepare for next
517 */
518 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
519 if (walk_state->op_info->flags & AML_NAMED) {
520 if (acpi_gbl_depth) {
521 acpi_gbl_depth--;
522 }
523
524 if (op->common.aml_opcode == AML_REGION_OP) {
525 /*
526 * Skip parsing of control method or opregion body,
527 * because we don't have enough info in the first pass
528 * to parse them correctly.
529 *
530 * Completed parsing an op_region declaration, we now
531 * know the length.
532 */
533 op->named.length = (u32) (parser_state->aml - op->named.data);
534 }
535 }
536
537 if (walk_state->op_info->flags & AML_CREATE) {
538 /*
539 * Backup to beginning of create_xXXfield declaration (1 for
540 * Opcode)
541 *
542 * body_length is unknown until we parse the body
543 */
544 op->named.length = (u32) (parser_state->aml - op->named.data);
545 }
546
547 /* This op complete, notify the dispatcher */
548
549 if (walk_state->ascending_callback != NULL) {
550 walk_state->op = op;
551 walk_state->opcode = op->common.aml_opcode;
552
553 status = walk_state->ascending_callback (walk_state);
554 status = acpi_ps_next_parse_state (walk_state, op, status);
555 if (status == AE_CTRL_PENDING) {
556 status = AE_OK;
557 goto close_this_op;
558 }
559 }
560
561
562close_this_op:
563 /*
564 * Finished one argument of the containing scope
565 */
566 parser_state->scope->parse_scope.arg_count--;
567
568 /* Finished with pre_op */
569
570 if (pre_op) {
571 acpi_ps_free_op (pre_op);
572 pre_op = NULL;
573 }
574
575 /* Close this Op (will result in parse subtree deletion) */
576
577 status2 = acpi_ps_complete_this_op (walk_state, op);
578 if (ACPI_FAILURE (status2)) {
579 return_ACPI_STATUS (status2);
580 }
581 op = NULL;
582
583 switch (status) {
584 case AE_OK:
585 break;
586
587
588 case AE_CTRL_TRANSFER:
589
590 /* We are about to transfer to a called method. */
591
592 walk_state->prev_op = op;
593 walk_state->prev_arg_types = walk_state->arg_types;
594 return_ACPI_STATUS (status);
595
596
597 case AE_CTRL_END:
598
599 acpi_ps_pop_scope (parser_state, &op,
600 &walk_state->arg_types, &walk_state->arg_count);
601
602 if (op) {
603 walk_state->op = op;
604 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
605 walk_state->opcode = op->common.aml_opcode;
606
607 status = walk_state->ascending_callback (walk_state);
608 status = acpi_ps_next_parse_state (walk_state, op, status);
609
610 status2 = acpi_ps_complete_this_op (walk_state, op);
611 if (ACPI_FAILURE (status2)) {
612 return_ACPI_STATUS (status2);
613 }
614 op = NULL;
615 }
616 status = AE_OK;
617 break;
618
619
620 case AE_CTRL_BREAK:
621 case AE_CTRL_CONTINUE:
622
623 /* Pop off scopes until we find the While */
624
625 while (!op || (op->common.aml_opcode != AML_WHILE_OP)) {
626 acpi_ps_pop_scope (parser_state, &op,
627 &walk_state->arg_types, &walk_state->arg_count);
628 }
629
630 /* Close this iteration of the While loop */
631
632 walk_state->op = op;
633 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
634 walk_state->opcode = op->common.aml_opcode;
635
636 status = walk_state->ascending_callback (walk_state);
637 status = acpi_ps_next_parse_state (walk_state, op, status);
638
639 status2 = acpi_ps_complete_this_op (walk_state, op);
640 if (ACPI_FAILURE (status2)) {
641 return_ACPI_STATUS (status2);
642 }
643 op = NULL;
644
645 status = AE_OK;
646 break;
647
648
649 case AE_CTRL_TERMINATE:
650
651 status = AE_OK;
652
653 /* Clean up */
654 do {
655 if (op) {
656 status2 = acpi_ps_complete_this_op (walk_state, op);
657 if (ACPI_FAILURE (status2)) {
658 return_ACPI_STATUS (status2);
659 }
660 }
661 acpi_ps_pop_scope (parser_state, &op,
662 &walk_state->arg_types, &walk_state->arg_count);
663
664 } while (op);
665
666 return_ACPI_STATUS (status);
667
668
669 default: /* All other non-AE_OK status */
670
671 do {
672 if (op) {
673 status2 = acpi_ps_complete_this_op (walk_state, op);
674 if (ACPI_FAILURE (status2)) {
675 return_ACPI_STATUS (status2);
676 }
677 }
678 acpi_ps_pop_scope (parser_state, &op,
679 &walk_state->arg_types, &walk_state->arg_count);
680
681 } while (op);
682
683
684 /*
685 * TBD: Cleanup parse ops on error
686 */
687#if 0
688 if (op == NULL) {
689 acpi_ps_pop_scope (parser_state, &op,
690 &walk_state->arg_types, &walk_state->arg_count);
691 }
692#endif
693 walk_state->prev_op = op;
694 walk_state->prev_arg_types = walk_state->arg_types;
695 return_ACPI_STATUS (status);
696 }
697
698 /* This scope complete? */
699
700 if (acpi_ps_has_completed_scope (parser_state)) {
701 acpi_ps_pop_scope (parser_state, &op,
702 &walk_state->arg_types, &walk_state->arg_count);
703 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op));
704 }
705 else {
706 op = NULL;
707 }
708
709 } /* while parser_state->Aml */
710
711
712 /*
713 * Complete the last Op (if not completed), and clear the scope stack.
714 * It is easily possible to end an AML "package" with an unbounded number
715 * of open scopes (such as when several ASL blocks are closed with
716 * sequential closing braces). We want to terminate each one cleanly.
717 */
718 ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "AML package complete at Op %p\n", op));
719 do {
720 if (op) {
721 if (walk_state->ascending_callback != NULL) {
722 walk_state->op = op;
723 walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
724 walk_state->opcode = op->common.aml_opcode;
725
726 status = walk_state->ascending_callback (walk_state);
727 status = acpi_ps_next_parse_state (walk_state, op, status);
728 if (status == AE_CTRL_PENDING) {
729 status = AE_OK;
730 goto close_this_op;
731 }
732
733 if (status == AE_CTRL_TERMINATE) {
734 status = AE_OK;
735
736 /* Clean up */
737 do {
738 if (op) {
739 status2 = acpi_ps_complete_this_op (walk_state, op);
740 if (ACPI_FAILURE (status2)) {
741 return_ACPI_STATUS (status2);
742 }
743 }
744
745 acpi_ps_pop_scope (parser_state, &op,
746 &walk_state->arg_types, &walk_state->arg_count);
747
748 } while (op);
749
750 return_ACPI_STATUS (status);
751 }
752
753 else if (ACPI_FAILURE (status)) {
754 /* First error is most important */
755
756 (void) acpi_ps_complete_this_op (walk_state, op);
757 return_ACPI_STATUS (status);
758 }
759 }
760
761 status2 = acpi_ps_complete_this_op (walk_state, op);
762 if (ACPI_FAILURE (status2)) {
763 return_ACPI_STATUS (status2);
764 }
765 }
766
767 acpi_ps_pop_scope (parser_state, &op, &walk_state->arg_types,
768 &walk_state->arg_count);
769
770 } while (op);
771
772 return_ACPI_STATUS (status);
773}
774
775