xref: /openbmc/linux/drivers/acpi/acpica/psloop.c (revision 95b482a8d31116f3f5c2a5089569393234d06385)
1*95b482a8SLen Brown /******************************************************************************
2*95b482a8SLen Brown  *
3*95b482a8SLen Brown  * Module Name: psloop - Main AML parse loop
4*95b482a8SLen Brown  *
5*95b482a8SLen Brown  *****************************************************************************/
6*95b482a8SLen Brown 
7*95b482a8SLen Brown /*
8*95b482a8SLen Brown  * Copyright (C) 2000 - 2008, Intel Corp.
9*95b482a8SLen Brown  * All rights reserved.
10*95b482a8SLen Brown  *
11*95b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
12*95b482a8SLen Brown  * modification, are permitted provided that the following conditions
13*95b482a8SLen Brown  * are met:
14*95b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
15*95b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
16*95b482a8SLen Brown  *    without modification.
17*95b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*95b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
19*95b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
20*95b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
21*95b482a8SLen Brown  *    binary redistribution.
22*95b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
23*95b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
24*95b482a8SLen Brown  *    from this software without specific prior written permission.
25*95b482a8SLen Brown  *
26*95b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
27*95b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
28*95b482a8SLen Brown  * Software Foundation.
29*95b482a8SLen Brown  *
30*95b482a8SLen Brown  * NO WARRANTY
31*95b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*95b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*95b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*95b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*95b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*95b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*95b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*95b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*95b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*95b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*95b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
42*95b482a8SLen Brown  */
43*95b482a8SLen Brown 
44*95b482a8SLen Brown /*
45*95b482a8SLen Brown  * Parse the AML and build an operation tree as most interpreters, (such as
46*95b482a8SLen Brown  * Perl) do. Parsing is done by hand rather than with a YACC generated parser
47*95b482a8SLen Brown  * to tightly constrain stack and dynamic memory usage. Parsing is kept
48*95b482a8SLen Brown  * flexible and the code fairly compact by parsing based on a list of AML
49*95b482a8SLen Brown  * opcode templates in aml_op_info[].
50*95b482a8SLen Brown  */
51*95b482a8SLen Brown 
52*95b482a8SLen Brown #include <acpi/acpi.h>
53*95b482a8SLen Brown #include <acpi/accommon.h>
54*95b482a8SLen Brown #include <acpi/acparser.h>
55*95b482a8SLen Brown #include <acpi/acdispat.h>
56*95b482a8SLen Brown #include <acpi/amlcode.h>
57*95b482a8SLen Brown 
58*95b482a8SLen Brown #define _COMPONENT          ACPI_PARSER
59*95b482a8SLen Brown ACPI_MODULE_NAME("psloop")
60*95b482a8SLen Brown 
61*95b482a8SLen Brown static u32 acpi_gbl_depth = 0;
62*95b482a8SLen Brown 
63*95b482a8SLen Brown /* Local prototypes */
64*95b482a8SLen Brown 
65*95b482a8SLen Brown static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state);
66*95b482a8SLen Brown 
67*95b482a8SLen Brown static acpi_status
68*95b482a8SLen Brown acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
69*95b482a8SLen Brown 		       u8 * aml_op_start,
70*95b482a8SLen Brown 		       union acpi_parse_object *unnamed_op,
71*95b482a8SLen Brown 		       union acpi_parse_object **op);
72*95b482a8SLen Brown 
73*95b482a8SLen Brown static acpi_status
74*95b482a8SLen Brown acpi_ps_create_op(struct acpi_walk_state *walk_state,
75*95b482a8SLen Brown 		  u8 * aml_op_start, union acpi_parse_object **new_op);
76*95b482a8SLen Brown 
77*95b482a8SLen Brown static acpi_status
78*95b482a8SLen Brown acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
79*95b482a8SLen Brown 		      u8 * aml_op_start, union acpi_parse_object *op);
80*95b482a8SLen Brown 
81*95b482a8SLen Brown static acpi_status
82*95b482a8SLen Brown acpi_ps_complete_op(struct acpi_walk_state *walk_state,
83*95b482a8SLen Brown 		    union acpi_parse_object **op, acpi_status status);
84*95b482a8SLen Brown 
85*95b482a8SLen Brown static acpi_status
86*95b482a8SLen Brown acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
87*95b482a8SLen Brown 			  union acpi_parse_object *op, acpi_status status);
88*95b482a8SLen Brown 
89*95b482a8SLen Brown /*******************************************************************************
90*95b482a8SLen Brown  *
91*95b482a8SLen Brown  * FUNCTION:    acpi_ps_get_aml_opcode
92*95b482a8SLen Brown  *
93*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
94*95b482a8SLen Brown  *
95*95b482a8SLen Brown  * RETURN:      Status
96*95b482a8SLen Brown  *
97*95b482a8SLen Brown  * DESCRIPTION: Extract the next AML opcode from the input stream.
98*95b482a8SLen Brown  *
99*95b482a8SLen Brown  ******************************************************************************/
100*95b482a8SLen Brown 
101*95b482a8SLen Brown static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
102*95b482a8SLen Brown {
103*95b482a8SLen Brown 
104*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state);
105*95b482a8SLen Brown 
106*95b482a8SLen Brown 	walk_state->aml_offset =
107*95b482a8SLen Brown 	    (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml,
108*95b482a8SLen Brown 				walk_state->parser_state.aml_start);
109*95b482a8SLen Brown 	walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state));
110*95b482a8SLen Brown 
111*95b482a8SLen Brown 	/*
112*95b482a8SLen Brown 	 * First cut to determine what we have found:
113*95b482a8SLen Brown 	 * 1) A valid AML opcode
114*95b482a8SLen Brown 	 * 2) A name string
115*95b482a8SLen Brown 	 * 3) An unknown/invalid opcode
116*95b482a8SLen Brown 	 */
117*95b482a8SLen Brown 	walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode);
118*95b482a8SLen Brown 
119*95b482a8SLen Brown 	switch (walk_state->op_info->class) {
120*95b482a8SLen Brown 	case AML_CLASS_ASCII:
121*95b482a8SLen Brown 	case AML_CLASS_PREFIX:
122*95b482a8SLen Brown 		/*
123*95b482a8SLen Brown 		 * Starts with a valid prefix or ASCII char, this is a name
124*95b482a8SLen Brown 		 * string. Convert the bare name string to a namepath.
125*95b482a8SLen Brown 		 */
126*95b482a8SLen Brown 		walk_state->opcode = AML_INT_NAMEPATH_OP;
127*95b482a8SLen Brown 		walk_state->arg_types = ARGP_NAMESTRING;
128*95b482a8SLen Brown 		break;
129*95b482a8SLen Brown 
130*95b482a8SLen Brown 	case AML_CLASS_UNKNOWN:
131*95b482a8SLen Brown 
132*95b482a8SLen Brown 		/* The opcode is unrecognized. Just skip unknown opcodes */
133*95b482a8SLen Brown 
134*95b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
135*95b482a8SLen Brown 			    "Found unknown opcode %X at AML address %p offset %X, ignoring",
136*95b482a8SLen Brown 			    walk_state->opcode, walk_state->parser_state.aml,
137*95b482a8SLen Brown 			    walk_state->aml_offset));
138*95b482a8SLen Brown 
139*95b482a8SLen Brown 		ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128);
140*95b482a8SLen Brown 
141*95b482a8SLen Brown 		/* Assume one-byte bad opcode */
142*95b482a8SLen Brown 
143*95b482a8SLen Brown 		walk_state->parser_state.aml++;
144*95b482a8SLen Brown 		return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
145*95b482a8SLen Brown 
146*95b482a8SLen Brown 	default:
147*95b482a8SLen Brown 
148*95b482a8SLen Brown 		/* Found opcode info, this is a normal opcode */
149*95b482a8SLen Brown 
150*95b482a8SLen Brown 		walk_state->parser_state.aml +=
151*95b482a8SLen Brown 		    acpi_ps_get_opcode_size(walk_state->opcode);
152*95b482a8SLen Brown 		walk_state->arg_types = walk_state->op_info->parse_args;
153*95b482a8SLen Brown 		break;
154*95b482a8SLen Brown 	}
155*95b482a8SLen Brown 
156*95b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
157*95b482a8SLen Brown }
158*95b482a8SLen Brown 
159*95b482a8SLen Brown /*******************************************************************************
160*95b482a8SLen Brown  *
161*95b482a8SLen Brown  * FUNCTION:    acpi_ps_build_named_op
162*95b482a8SLen Brown  *
163*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
164*95b482a8SLen Brown  *              aml_op_start        - Begin of named Op in AML
165*95b482a8SLen Brown  *              unnamed_op          - Early Op (not a named Op)
166*95b482a8SLen Brown  *              Op                  - Returned Op
167*95b482a8SLen Brown  *
168*95b482a8SLen Brown  * RETURN:      Status
169*95b482a8SLen Brown  *
170*95b482a8SLen Brown  * DESCRIPTION: Parse a named Op
171*95b482a8SLen Brown  *
172*95b482a8SLen Brown  ******************************************************************************/
173*95b482a8SLen Brown 
174*95b482a8SLen Brown static acpi_status
175*95b482a8SLen Brown acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
176*95b482a8SLen Brown 		       u8 * aml_op_start,
177*95b482a8SLen Brown 		       union acpi_parse_object *unnamed_op,
178*95b482a8SLen Brown 		       union acpi_parse_object **op)
179*95b482a8SLen Brown {
180*95b482a8SLen Brown 	acpi_status status = AE_OK;
181*95b482a8SLen Brown 	union acpi_parse_object *arg = NULL;
182*95b482a8SLen Brown 
183*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state);
184*95b482a8SLen Brown 
185*95b482a8SLen Brown 	unnamed_op->common.value.arg = NULL;
186*95b482a8SLen Brown 	unnamed_op->common.arg_list_length = 0;
187*95b482a8SLen Brown 	unnamed_op->common.aml_opcode = walk_state->opcode;
188*95b482a8SLen Brown 
189*95b482a8SLen Brown 	/*
190*95b482a8SLen Brown 	 * Get and append arguments until we find the node that contains
191*95b482a8SLen Brown 	 * the name (the type ARGP_NAME).
192*95b482a8SLen Brown 	 */
193*95b482a8SLen Brown 	while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
194*95b482a8SLen Brown 	       (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) {
195*95b482a8SLen Brown 		status =
196*95b482a8SLen Brown 		    acpi_ps_get_next_arg(walk_state,
197*95b482a8SLen Brown 					 &(walk_state->parser_state),
198*95b482a8SLen Brown 					 GET_CURRENT_ARG_TYPE(walk_state->
199*95b482a8SLen Brown 							      arg_types), &arg);
200*95b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
201*95b482a8SLen Brown 			return_ACPI_STATUS(status);
202*95b482a8SLen Brown 		}
203*95b482a8SLen Brown 
204*95b482a8SLen Brown 		acpi_ps_append_arg(unnamed_op, arg);
205*95b482a8SLen Brown 		INCREMENT_ARG_LIST(walk_state->arg_types);
206*95b482a8SLen Brown 	}
207*95b482a8SLen Brown 
208*95b482a8SLen Brown 	/*
209*95b482a8SLen Brown 	 * Make sure that we found a NAME and didn't run out of arguments
210*95b482a8SLen Brown 	 */
211*95b482a8SLen Brown 	if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) {
212*95b482a8SLen Brown 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
213*95b482a8SLen Brown 	}
214*95b482a8SLen Brown 
215*95b482a8SLen Brown 	/* We know that this arg is a name, move to next arg */
216*95b482a8SLen Brown 
217*95b482a8SLen Brown 	INCREMENT_ARG_LIST(walk_state->arg_types);
218*95b482a8SLen Brown 
219*95b482a8SLen Brown 	/*
220*95b482a8SLen Brown 	 * Find the object. This will either insert the object into
221*95b482a8SLen Brown 	 * the namespace or simply look it up
222*95b482a8SLen Brown 	 */
223*95b482a8SLen Brown 	walk_state->op = NULL;
224*95b482a8SLen Brown 
225*95b482a8SLen Brown 	status = walk_state->descending_callback(walk_state, op);
226*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
227*95b482a8SLen Brown 		ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog"));
228*95b482a8SLen Brown 		return_ACPI_STATUS(status);
229*95b482a8SLen Brown 	}
230*95b482a8SLen Brown 
231*95b482a8SLen Brown 	if (!*op) {
232*95b482a8SLen Brown 		return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
233*95b482a8SLen Brown 	}
234*95b482a8SLen Brown 
235*95b482a8SLen Brown 	status = acpi_ps_next_parse_state(walk_state, *op, status);
236*95b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
237*95b482a8SLen Brown 		if (status == AE_CTRL_PENDING) {
238*95b482a8SLen Brown 			return_ACPI_STATUS(AE_CTRL_PARSE_PENDING);
239*95b482a8SLen Brown 		}
240*95b482a8SLen Brown 		return_ACPI_STATUS(status);
241*95b482a8SLen Brown 	}
242*95b482a8SLen Brown 
243*95b482a8SLen Brown 	acpi_ps_append_arg(*op, unnamed_op->common.value.arg);
244*95b482a8SLen Brown 	acpi_gbl_depth++;
245*95b482a8SLen Brown 
246*95b482a8SLen Brown 	if ((*op)->common.aml_opcode == AML_REGION_OP ||
247*95b482a8SLen Brown 	    (*op)->common.aml_opcode == AML_DATA_REGION_OP) {
248*95b482a8SLen Brown 		/*
249*95b482a8SLen Brown 		 * Defer final parsing of an operation_region body, because we don't
250*95b482a8SLen Brown 		 * have enough info in the first pass to parse it correctly (i.e.,
251*95b482a8SLen Brown 		 * there may be method calls within the term_arg elements of the body.)
252*95b482a8SLen Brown 		 *
253*95b482a8SLen Brown 		 * However, we must continue parsing because the opregion is not a
254*95b482a8SLen Brown 		 * standalone package -- we don't know where the end is at this point.
255*95b482a8SLen Brown 		 *
256*95b482a8SLen Brown 		 * (Length is unknown until parse of the body complete)
257*95b482a8SLen Brown 		 */
258*95b482a8SLen Brown 		(*op)->named.data = aml_op_start;
259*95b482a8SLen Brown 		(*op)->named.length = 0;
260*95b482a8SLen Brown 	}
261*95b482a8SLen Brown 
262*95b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
263*95b482a8SLen Brown }
264*95b482a8SLen Brown 
265*95b482a8SLen Brown /*******************************************************************************
266*95b482a8SLen Brown  *
267*95b482a8SLen Brown  * FUNCTION:    acpi_ps_create_op
268*95b482a8SLen Brown  *
269*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
270*95b482a8SLen Brown  *              aml_op_start        - Op start in AML
271*95b482a8SLen Brown  *              new_op              - Returned Op
272*95b482a8SLen Brown  *
273*95b482a8SLen Brown  * RETURN:      Status
274*95b482a8SLen Brown  *
275*95b482a8SLen Brown  * DESCRIPTION: Get Op from AML
276*95b482a8SLen Brown  *
277*95b482a8SLen Brown  ******************************************************************************/
278*95b482a8SLen Brown 
279*95b482a8SLen Brown static acpi_status
280*95b482a8SLen Brown acpi_ps_create_op(struct acpi_walk_state *walk_state,
281*95b482a8SLen Brown 		  u8 * aml_op_start, union acpi_parse_object **new_op)
282*95b482a8SLen Brown {
283*95b482a8SLen Brown 	acpi_status status = AE_OK;
284*95b482a8SLen Brown 	union acpi_parse_object *op;
285*95b482a8SLen Brown 	union acpi_parse_object *named_op = NULL;
286*95b482a8SLen Brown 	union acpi_parse_object *parent_scope;
287*95b482a8SLen Brown 	u8 argument_count;
288*95b482a8SLen Brown 	const struct acpi_opcode_info *op_info;
289*95b482a8SLen Brown 
290*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state);
291*95b482a8SLen Brown 
292*95b482a8SLen Brown 	status = acpi_ps_get_aml_opcode(walk_state);
293*95b482a8SLen Brown 	if (status == AE_CTRL_PARSE_CONTINUE) {
294*95b482a8SLen Brown 		return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
295*95b482a8SLen Brown 	}
296*95b482a8SLen Brown 
297*95b482a8SLen Brown 	/* Create Op structure and append to parent's argument list */
298*95b482a8SLen Brown 
299*95b482a8SLen Brown 	walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode);
300*95b482a8SLen Brown 	op = acpi_ps_alloc_op(walk_state->opcode);
301*95b482a8SLen Brown 	if (!op) {
302*95b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
303*95b482a8SLen Brown 	}
304*95b482a8SLen Brown 
305*95b482a8SLen Brown 	if (walk_state->op_info->flags & AML_NAMED) {
306*95b482a8SLen Brown 		status =
307*95b482a8SLen Brown 		    acpi_ps_build_named_op(walk_state, aml_op_start, op,
308*95b482a8SLen Brown 					   &named_op);
309*95b482a8SLen Brown 		acpi_ps_free_op(op);
310*95b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
311*95b482a8SLen Brown 			return_ACPI_STATUS(status);
312*95b482a8SLen Brown 		}
313*95b482a8SLen Brown 
314*95b482a8SLen Brown 		*new_op = named_op;
315*95b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
316*95b482a8SLen Brown 	}
317*95b482a8SLen Brown 
318*95b482a8SLen Brown 	/* Not a named opcode, just allocate Op and append to parent */
319*95b482a8SLen Brown 
320*95b482a8SLen Brown 	if (walk_state->op_info->flags & AML_CREATE) {
321*95b482a8SLen Brown 		/*
322*95b482a8SLen Brown 		 * Backup to beginning of create_xXXfield declaration
323*95b482a8SLen Brown 		 * body_length is unknown until we parse the body
324*95b482a8SLen Brown 		 */
325*95b482a8SLen Brown 		op->named.data = aml_op_start;
326*95b482a8SLen Brown 		op->named.length = 0;
327*95b482a8SLen Brown 	}
328*95b482a8SLen Brown 
329*95b482a8SLen Brown 	if (walk_state->opcode == AML_BANK_FIELD_OP) {
330*95b482a8SLen Brown 		/*
331*95b482a8SLen Brown 		 * Backup to beginning of bank_field declaration
332*95b482a8SLen Brown 		 * body_length is unknown until we parse the body
333*95b482a8SLen Brown 		 */
334*95b482a8SLen Brown 		op->named.data = aml_op_start;
335*95b482a8SLen Brown 		op->named.length = 0;
336*95b482a8SLen Brown 	}
337*95b482a8SLen Brown 
338*95b482a8SLen Brown 	parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state));
339*95b482a8SLen Brown 	acpi_ps_append_arg(parent_scope, op);
340*95b482a8SLen Brown 
341*95b482a8SLen Brown 	if (parent_scope) {
342*95b482a8SLen Brown 		op_info =
343*95b482a8SLen Brown 		    acpi_ps_get_opcode_info(parent_scope->common.aml_opcode);
344*95b482a8SLen Brown 		if (op_info->flags & AML_HAS_TARGET) {
345*95b482a8SLen Brown 			argument_count =
346*95b482a8SLen Brown 			    acpi_ps_get_argument_count(op_info->type);
347*95b482a8SLen Brown 			if (parent_scope->common.arg_list_length >
348*95b482a8SLen Brown 			    argument_count) {
349*95b482a8SLen Brown 				op->common.flags |= ACPI_PARSEOP_TARGET;
350*95b482a8SLen Brown 			}
351*95b482a8SLen Brown 		} else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) {
352*95b482a8SLen Brown 			op->common.flags |= ACPI_PARSEOP_TARGET;
353*95b482a8SLen Brown 		}
354*95b482a8SLen Brown 	}
355*95b482a8SLen Brown 
356*95b482a8SLen Brown 	if (walk_state->descending_callback != NULL) {
357*95b482a8SLen Brown 		/*
358*95b482a8SLen Brown 		 * Find the object. This will either insert the object into
359*95b482a8SLen Brown 		 * the namespace or simply look it up
360*95b482a8SLen Brown 		 */
361*95b482a8SLen Brown 		walk_state->op = *new_op = op;
362*95b482a8SLen Brown 
363*95b482a8SLen Brown 		status = walk_state->descending_callback(walk_state, &op);
364*95b482a8SLen Brown 		status = acpi_ps_next_parse_state(walk_state, op, status);
365*95b482a8SLen Brown 		if (status == AE_CTRL_PENDING) {
366*95b482a8SLen Brown 			status = AE_CTRL_PARSE_PENDING;
367*95b482a8SLen Brown 		}
368*95b482a8SLen Brown 	}
369*95b482a8SLen Brown 
370*95b482a8SLen Brown 	return_ACPI_STATUS(status);
371*95b482a8SLen Brown }
372*95b482a8SLen Brown 
373*95b482a8SLen Brown /*******************************************************************************
374*95b482a8SLen Brown  *
375*95b482a8SLen Brown  * FUNCTION:    acpi_ps_get_arguments
376*95b482a8SLen Brown  *
377*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
378*95b482a8SLen Brown  *              aml_op_start        - Op start in AML
379*95b482a8SLen Brown  *              Op                  - Current Op
380*95b482a8SLen Brown  *
381*95b482a8SLen Brown  * RETURN:      Status
382*95b482a8SLen Brown  *
383*95b482a8SLen Brown  * DESCRIPTION: Get arguments for passed Op.
384*95b482a8SLen Brown  *
385*95b482a8SLen Brown  ******************************************************************************/
386*95b482a8SLen Brown 
387*95b482a8SLen Brown static acpi_status
388*95b482a8SLen Brown acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
389*95b482a8SLen Brown 		      u8 * aml_op_start, union acpi_parse_object *op)
390*95b482a8SLen Brown {
391*95b482a8SLen Brown 	acpi_status status = AE_OK;
392*95b482a8SLen Brown 	union acpi_parse_object *arg = NULL;
393*95b482a8SLen Brown 
394*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
395*95b482a8SLen Brown 
396*95b482a8SLen Brown 	switch (op->common.aml_opcode) {
397*95b482a8SLen Brown 	case AML_BYTE_OP:	/* AML_BYTEDATA_ARG */
398*95b482a8SLen Brown 	case AML_WORD_OP:	/* AML_WORDDATA_ARG */
399*95b482a8SLen Brown 	case AML_DWORD_OP:	/* AML_DWORDATA_ARG */
400*95b482a8SLen Brown 	case AML_QWORD_OP:	/* AML_QWORDATA_ARG */
401*95b482a8SLen Brown 	case AML_STRING_OP:	/* AML_ASCIICHARLIST_ARG */
402*95b482a8SLen Brown 
403*95b482a8SLen Brown 		/* Fill in constant or string argument directly */
404*95b482a8SLen Brown 
405*95b482a8SLen Brown 		acpi_ps_get_next_simple_arg(&(walk_state->parser_state),
406*95b482a8SLen Brown 					    GET_CURRENT_ARG_TYPE(walk_state->
407*95b482a8SLen Brown 								 arg_types),
408*95b482a8SLen Brown 					    op);
409*95b482a8SLen Brown 		break;
410*95b482a8SLen Brown 
411*95b482a8SLen Brown 	case AML_INT_NAMEPATH_OP:	/* AML_NAMESTRING_ARG */
412*95b482a8SLen Brown 
413*95b482a8SLen Brown 		status =
414*95b482a8SLen Brown 		    acpi_ps_get_next_namepath(walk_state,
415*95b482a8SLen Brown 					      &(walk_state->parser_state), op,
416*95b482a8SLen Brown 					      1);
417*95b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
418*95b482a8SLen Brown 			return_ACPI_STATUS(status);
419*95b482a8SLen Brown 		}
420*95b482a8SLen Brown 
421*95b482a8SLen Brown 		walk_state->arg_types = 0;
422*95b482a8SLen Brown 		break;
423*95b482a8SLen Brown 
424*95b482a8SLen Brown 	default:
425*95b482a8SLen Brown 		/*
426*95b482a8SLen Brown 		 * Op is not a constant or string, append each argument to the Op
427*95b482a8SLen Brown 		 */
428*95b482a8SLen Brown 		while (GET_CURRENT_ARG_TYPE(walk_state->arg_types)
429*95b482a8SLen Brown 		       && !walk_state->arg_count) {
430*95b482a8SLen Brown 			walk_state->aml_offset =
431*95b482a8SLen Brown 			    (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml,
432*95b482a8SLen Brown 						walk_state->parser_state.
433*95b482a8SLen Brown 						aml_start);
434*95b482a8SLen Brown 
435*95b482a8SLen Brown 			status =
436*95b482a8SLen Brown 			    acpi_ps_get_next_arg(walk_state,
437*95b482a8SLen Brown 						 &(walk_state->parser_state),
438*95b482a8SLen Brown 						 GET_CURRENT_ARG_TYPE
439*95b482a8SLen Brown 						 (walk_state->arg_types), &arg);
440*95b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
441*95b482a8SLen Brown 				return_ACPI_STATUS(status);
442*95b482a8SLen Brown 			}
443*95b482a8SLen Brown 
444*95b482a8SLen Brown 			if (arg) {
445*95b482a8SLen Brown 				arg->common.aml_offset = walk_state->aml_offset;
446*95b482a8SLen Brown 				acpi_ps_append_arg(op, arg);
447*95b482a8SLen Brown 			}
448*95b482a8SLen Brown 
449*95b482a8SLen Brown 			INCREMENT_ARG_LIST(walk_state->arg_types);
450*95b482a8SLen Brown 		}
451*95b482a8SLen Brown 
452*95b482a8SLen Brown 		/* Special processing for certain opcodes */
453*95b482a8SLen Brown 
454*95b482a8SLen Brown 		/* TBD (remove): Temporary mechanism to disable this code if needed */
455*95b482a8SLen Brown 
456*95b482a8SLen Brown #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
457*95b482a8SLen Brown 
458*95b482a8SLen Brown 		if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) &&
459*95b482a8SLen Brown 		    ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
460*95b482a8SLen Brown 			/*
461*95b482a8SLen Brown 			 * We want to skip If/Else/While constructs during Pass1 because we
462*95b482a8SLen Brown 			 * want to actually conditionally execute the code during Pass2.
463*95b482a8SLen Brown 			 *
464*95b482a8SLen Brown 			 * Except for disassembly, where we always want to walk the
465*95b482a8SLen Brown 			 * If/Else/While packages
466*95b482a8SLen Brown 			 */
467*95b482a8SLen Brown 			switch (op->common.aml_opcode) {
468*95b482a8SLen Brown 			case AML_IF_OP:
469*95b482a8SLen Brown 			case AML_ELSE_OP:
470*95b482a8SLen Brown 			case AML_WHILE_OP:
471*95b482a8SLen Brown 
472*95b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
473*95b482a8SLen Brown 						  "Pass1: Skipping an If/Else/While body\n"));
474*95b482a8SLen Brown 
475*95b482a8SLen Brown 				/* Skip body of if/else/while in pass 1 */
476*95b482a8SLen Brown 
477*95b482a8SLen Brown 				walk_state->parser_state.aml =
478*95b482a8SLen Brown 				    walk_state->parser_state.pkg_end;
479*95b482a8SLen Brown 				walk_state->arg_count = 0;
480*95b482a8SLen Brown 				break;
481*95b482a8SLen Brown 
482*95b482a8SLen Brown 			default:
483*95b482a8SLen Brown 				break;
484*95b482a8SLen Brown 			}
485*95b482a8SLen Brown 		}
486*95b482a8SLen Brown #endif
487*95b482a8SLen Brown 
488*95b482a8SLen Brown 		switch (op->common.aml_opcode) {
489*95b482a8SLen Brown 		case AML_METHOD_OP:
490*95b482a8SLen Brown 			/*
491*95b482a8SLen Brown 			 * Skip parsing of control method because we don't have enough
492*95b482a8SLen Brown 			 * info in the first pass to parse it correctly.
493*95b482a8SLen Brown 			 *
494*95b482a8SLen Brown 			 * Save the length and address of the body
495*95b482a8SLen Brown 			 */
496*95b482a8SLen Brown 			op->named.data = walk_state->parser_state.aml;
497*95b482a8SLen Brown 			op->named.length = (u32)
498*95b482a8SLen Brown 			    (walk_state->parser_state.pkg_end -
499*95b482a8SLen Brown 			     walk_state->parser_state.aml);
500*95b482a8SLen Brown 
501*95b482a8SLen Brown 			/* Skip body of method */
502*95b482a8SLen Brown 
503*95b482a8SLen Brown 			walk_state->parser_state.aml =
504*95b482a8SLen Brown 			    walk_state->parser_state.pkg_end;
505*95b482a8SLen Brown 			walk_state->arg_count = 0;
506*95b482a8SLen Brown 			break;
507*95b482a8SLen Brown 
508*95b482a8SLen Brown 		case AML_BUFFER_OP:
509*95b482a8SLen Brown 		case AML_PACKAGE_OP:
510*95b482a8SLen Brown 		case AML_VAR_PACKAGE_OP:
511*95b482a8SLen Brown 
512*95b482a8SLen Brown 			if ((op->common.parent) &&
513*95b482a8SLen Brown 			    (op->common.parent->common.aml_opcode ==
514*95b482a8SLen Brown 			     AML_NAME_OP)
515*95b482a8SLen Brown 			    && (walk_state->pass_number <=
516*95b482a8SLen Brown 				ACPI_IMODE_LOAD_PASS2)) {
517*95b482a8SLen Brown 				/*
518*95b482a8SLen Brown 				 * Skip parsing of Buffers and Packages because we don't have
519*95b482a8SLen Brown 				 * enough info in the first pass to parse them correctly.
520*95b482a8SLen Brown 				 */
521*95b482a8SLen Brown 				op->named.data = aml_op_start;
522*95b482a8SLen Brown 				op->named.length = (u32)
523*95b482a8SLen Brown 				    (walk_state->parser_state.pkg_end -
524*95b482a8SLen Brown 				     aml_op_start);
525*95b482a8SLen Brown 
526*95b482a8SLen Brown 				/* Skip body */
527*95b482a8SLen Brown 
528*95b482a8SLen Brown 				walk_state->parser_state.aml =
529*95b482a8SLen Brown 				    walk_state->parser_state.pkg_end;
530*95b482a8SLen Brown 				walk_state->arg_count = 0;
531*95b482a8SLen Brown 			}
532*95b482a8SLen Brown 			break;
533*95b482a8SLen Brown 
534*95b482a8SLen Brown 		case AML_WHILE_OP:
535*95b482a8SLen Brown 
536*95b482a8SLen Brown 			if (walk_state->control_state) {
537*95b482a8SLen Brown 				walk_state->control_state->control.package_end =
538*95b482a8SLen Brown 				    walk_state->parser_state.pkg_end;
539*95b482a8SLen Brown 			}
540*95b482a8SLen Brown 			break;
541*95b482a8SLen Brown 
542*95b482a8SLen Brown 		default:
543*95b482a8SLen Brown 
544*95b482a8SLen Brown 			/* No action for all other opcodes */
545*95b482a8SLen Brown 			break;
546*95b482a8SLen Brown 		}
547*95b482a8SLen Brown 
548*95b482a8SLen Brown 		break;
549*95b482a8SLen Brown 	}
550*95b482a8SLen Brown 
551*95b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
552*95b482a8SLen Brown }
553*95b482a8SLen Brown 
554*95b482a8SLen Brown /*******************************************************************************
555*95b482a8SLen Brown  *
556*95b482a8SLen Brown  * FUNCTION:    acpi_ps_complete_op
557*95b482a8SLen Brown  *
558*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
559*95b482a8SLen Brown  *              Op                  - Returned Op
560*95b482a8SLen Brown  *              Status              - Parse status before complete Op
561*95b482a8SLen Brown  *
562*95b482a8SLen Brown  * RETURN:      Status
563*95b482a8SLen Brown  *
564*95b482a8SLen Brown  * DESCRIPTION: Complete Op
565*95b482a8SLen Brown  *
566*95b482a8SLen Brown  ******************************************************************************/
567*95b482a8SLen Brown 
568*95b482a8SLen Brown static acpi_status
569*95b482a8SLen Brown acpi_ps_complete_op(struct acpi_walk_state *walk_state,
570*95b482a8SLen Brown 		    union acpi_parse_object **op, acpi_status status)
571*95b482a8SLen Brown {
572*95b482a8SLen Brown 	acpi_status status2;
573*95b482a8SLen Brown 
574*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state);
575*95b482a8SLen Brown 
576*95b482a8SLen Brown 	/*
577*95b482a8SLen Brown 	 * Finished one argument of the containing scope
578*95b482a8SLen Brown 	 */
579*95b482a8SLen Brown 	walk_state->parser_state.scope->parse_scope.arg_count--;
580*95b482a8SLen Brown 
581*95b482a8SLen Brown 	/* Close this Op (will result in parse subtree deletion) */
582*95b482a8SLen Brown 
583*95b482a8SLen Brown 	status2 = acpi_ps_complete_this_op(walk_state, *op);
584*95b482a8SLen Brown 	if (ACPI_FAILURE(status2)) {
585*95b482a8SLen Brown 		return_ACPI_STATUS(status2);
586*95b482a8SLen Brown 	}
587*95b482a8SLen Brown 
588*95b482a8SLen Brown 	*op = NULL;
589*95b482a8SLen Brown 
590*95b482a8SLen Brown 	switch (status) {
591*95b482a8SLen Brown 	case AE_OK:
592*95b482a8SLen Brown 		break;
593*95b482a8SLen Brown 
594*95b482a8SLen Brown 	case AE_CTRL_TRANSFER:
595*95b482a8SLen Brown 
596*95b482a8SLen Brown 		/* We are about to transfer to a called method */
597*95b482a8SLen Brown 
598*95b482a8SLen Brown 		walk_state->prev_op = NULL;
599*95b482a8SLen Brown 		walk_state->prev_arg_types = walk_state->arg_types;
600*95b482a8SLen Brown 		return_ACPI_STATUS(status);
601*95b482a8SLen Brown 
602*95b482a8SLen Brown 	case AE_CTRL_END:
603*95b482a8SLen Brown 
604*95b482a8SLen Brown 		acpi_ps_pop_scope(&(walk_state->parser_state), op,
605*95b482a8SLen Brown 				  &walk_state->arg_types,
606*95b482a8SLen Brown 				  &walk_state->arg_count);
607*95b482a8SLen Brown 
608*95b482a8SLen Brown 		if (*op) {
609*95b482a8SLen Brown 			walk_state->op = *op;
610*95b482a8SLen Brown 			walk_state->op_info =
611*95b482a8SLen Brown 			    acpi_ps_get_opcode_info((*op)->common.aml_opcode);
612*95b482a8SLen Brown 			walk_state->opcode = (*op)->common.aml_opcode;
613*95b482a8SLen Brown 
614*95b482a8SLen Brown 			status = walk_state->ascending_callback(walk_state);
615*95b482a8SLen Brown 			status =
616*95b482a8SLen Brown 			    acpi_ps_next_parse_state(walk_state, *op, status);
617*95b482a8SLen Brown 
618*95b482a8SLen Brown 			status2 = acpi_ps_complete_this_op(walk_state, *op);
619*95b482a8SLen Brown 			if (ACPI_FAILURE(status2)) {
620*95b482a8SLen Brown 				return_ACPI_STATUS(status2);
621*95b482a8SLen Brown 			}
622*95b482a8SLen Brown 		}
623*95b482a8SLen Brown 
624*95b482a8SLen Brown 		status = AE_OK;
625*95b482a8SLen Brown 		break;
626*95b482a8SLen Brown 
627*95b482a8SLen Brown 	case AE_CTRL_BREAK:
628*95b482a8SLen Brown 	case AE_CTRL_CONTINUE:
629*95b482a8SLen Brown 
630*95b482a8SLen Brown 		/* Pop off scopes until we find the While */
631*95b482a8SLen Brown 
632*95b482a8SLen Brown 		while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) {
633*95b482a8SLen Brown 			acpi_ps_pop_scope(&(walk_state->parser_state), op,
634*95b482a8SLen Brown 					  &walk_state->arg_types,
635*95b482a8SLen Brown 					  &walk_state->arg_count);
636*95b482a8SLen Brown 		}
637*95b482a8SLen Brown 
638*95b482a8SLen Brown 		/* Close this iteration of the While loop */
639*95b482a8SLen Brown 
640*95b482a8SLen Brown 		walk_state->op = *op;
641*95b482a8SLen Brown 		walk_state->op_info =
642*95b482a8SLen Brown 		    acpi_ps_get_opcode_info((*op)->common.aml_opcode);
643*95b482a8SLen Brown 		walk_state->opcode = (*op)->common.aml_opcode;
644*95b482a8SLen Brown 
645*95b482a8SLen Brown 		status = walk_state->ascending_callback(walk_state);
646*95b482a8SLen Brown 		status = acpi_ps_next_parse_state(walk_state, *op, status);
647*95b482a8SLen Brown 
648*95b482a8SLen Brown 		status2 = acpi_ps_complete_this_op(walk_state, *op);
649*95b482a8SLen Brown 		if (ACPI_FAILURE(status2)) {
650*95b482a8SLen Brown 			return_ACPI_STATUS(status2);
651*95b482a8SLen Brown 		}
652*95b482a8SLen Brown 
653*95b482a8SLen Brown 		status = AE_OK;
654*95b482a8SLen Brown 		break;
655*95b482a8SLen Brown 
656*95b482a8SLen Brown 	case AE_CTRL_TERMINATE:
657*95b482a8SLen Brown 
658*95b482a8SLen Brown 		/* Clean up */
659*95b482a8SLen Brown 		do {
660*95b482a8SLen Brown 			if (*op) {
661*95b482a8SLen Brown 				status2 =
662*95b482a8SLen Brown 				    acpi_ps_complete_this_op(walk_state, *op);
663*95b482a8SLen Brown 				if (ACPI_FAILURE(status2)) {
664*95b482a8SLen Brown 					return_ACPI_STATUS(status2);
665*95b482a8SLen Brown 				}
666*95b482a8SLen Brown 
667*95b482a8SLen Brown 				acpi_ut_delete_generic_state
668*95b482a8SLen Brown 				    (acpi_ut_pop_generic_state
669*95b482a8SLen Brown 				     (&walk_state->control_state));
670*95b482a8SLen Brown 			}
671*95b482a8SLen Brown 
672*95b482a8SLen Brown 			acpi_ps_pop_scope(&(walk_state->parser_state), op,
673*95b482a8SLen Brown 					  &walk_state->arg_types,
674*95b482a8SLen Brown 					  &walk_state->arg_count);
675*95b482a8SLen Brown 
676*95b482a8SLen Brown 		} while (*op);
677*95b482a8SLen Brown 
678*95b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
679*95b482a8SLen Brown 
680*95b482a8SLen Brown 	default:		/* All other non-AE_OK status */
681*95b482a8SLen Brown 
682*95b482a8SLen Brown 		do {
683*95b482a8SLen Brown 			if (*op) {
684*95b482a8SLen Brown 				status2 =
685*95b482a8SLen Brown 				    acpi_ps_complete_this_op(walk_state, *op);
686*95b482a8SLen Brown 				if (ACPI_FAILURE(status2)) {
687*95b482a8SLen Brown 					return_ACPI_STATUS(status2);
688*95b482a8SLen Brown 				}
689*95b482a8SLen Brown 			}
690*95b482a8SLen Brown 
691*95b482a8SLen Brown 			acpi_ps_pop_scope(&(walk_state->parser_state), op,
692*95b482a8SLen Brown 					  &walk_state->arg_types,
693*95b482a8SLen Brown 					  &walk_state->arg_count);
694*95b482a8SLen Brown 
695*95b482a8SLen Brown 		} while (*op);
696*95b482a8SLen Brown 
697*95b482a8SLen Brown #if 0
698*95b482a8SLen Brown 		/*
699*95b482a8SLen Brown 		 * TBD: Cleanup parse ops on error
700*95b482a8SLen Brown 		 */
701*95b482a8SLen Brown 		if (*op == NULL) {
702*95b482a8SLen Brown 			acpi_ps_pop_scope(parser_state, op,
703*95b482a8SLen Brown 					  &walk_state->arg_types,
704*95b482a8SLen Brown 					  &walk_state->arg_count);
705*95b482a8SLen Brown 		}
706*95b482a8SLen Brown #endif
707*95b482a8SLen Brown 		walk_state->prev_op = NULL;
708*95b482a8SLen Brown 		walk_state->prev_arg_types = walk_state->arg_types;
709*95b482a8SLen Brown 		return_ACPI_STATUS(status);
710*95b482a8SLen Brown 	}
711*95b482a8SLen Brown 
712*95b482a8SLen Brown 	/* This scope complete? */
713*95b482a8SLen Brown 
714*95b482a8SLen Brown 	if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) {
715*95b482a8SLen Brown 		acpi_ps_pop_scope(&(walk_state->parser_state), op,
716*95b482a8SLen Brown 				  &walk_state->arg_types,
717*95b482a8SLen Brown 				  &walk_state->arg_count);
718*95b482a8SLen Brown 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op));
719*95b482a8SLen Brown 	} else {
720*95b482a8SLen Brown 		*op = NULL;
721*95b482a8SLen Brown 	}
722*95b482a8SLen Brown 
723*95b482a8SLen Brown 	ACPI_PREEMPTION_POINT();
724*95b482a8SLen Brown 
725*95b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
726*95b482a8SLen Brown }
727*95b482a8SLen Brown 
728*95b482a8SLen Brown /*******************************************************************************
729*95b482a8SLen Brown  *
730*95b482a8SLen Brown  * FUNCTION:    acpi_ps_complete_final_op
731*95b482a8SLen Brown  *
732*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
733*95b482a8SLen Brown  *              Op                  - Current Op
734*95b482a8SLen Brown  *              Status              - Current parse status before complete last
735*95b482a8SLen Brown  *                                    Op
736*95b482a8SLen Brown  *
737*95b482a8SLen Brown  * RETURN:      Status
738*95b482a8SLen Brown  *
739*95b482a8SLen Brown  * DESCRIPTION: Complete last Op.
740*95b482a8SLen Brown  *
741*95b482a8SLen Brown  ******************************************************************************/
742*95b482a8SLen Brown 
743*95b482a8SLen Brown static acpi_status
744*95b482a8SLen Brown acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
745*95b482a8SLen Brown 			  union acpi_parse_object *op, acpi_status status)
746*95b482a8SLen Brown {
747*95b482a8SLen Brown 	acpi_status status2;
748*95b482a8SLen Brown 
749*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state);
750*95b482a8SLen Brown 
751*95b482a8SLen Brown 	/*
752*95b482a8SLen Brown 	 * Complete the last Op (if not completed), and clear the scope stack.
753*95b482a8SLen Brown 	 * It is easily possible to end an AML "package" with an unbounded number
754*95b482a8SLen Brown 	 * of open scopes (such as when several ASL blocks are closed with
755*95b482a8SLen Brown 	 * sequential closing braces). We want to terminate each one cleanly.
756*95b482a8SLen Brown 	 */
757*95b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n",
758*95b482a8SLen Brown 			  op));
759*95b482a8SLen Brown 	do {
760*95b482a8SLen Brown 		if (op) {
761*95b482a8SLen Brown 			if (walk_state->ascending_callback != NULL) {
762*95b482a8SLen Brown 				walk_state->op = op;
763*95b482a8SLen Brown 				walk_state->op_info =
764*95b482a8SLen Brown 				    acpi_ps_get_opcode_info(op->common.
765*95b482a8SLen Brown 							    aml_opcode);
766*95b482a8SLen Brown 				walk_state->opcode = op->common.aml_opcode;
767*95b482a8SLen Brown 
768*95b482a8SLen Brown 				status =
769*95b482a8SLen Brown 				    walk_state->ascending_callback(walk_state);
770*95b482a8SLen Brown 				status =
771*95b482a8SLen Brown 				    acpi_ps_next_parse_state(walk_state, op,
772*95b482a8SLen Brown 							     status);
773*95b482a8SLen Brown 				if (status == AE_CTRL_PENDING) {
774*95b482a8SLen Brown 					status =
775*95b482a8SLen Brown 					    acpi_ps_complete_op(walk_state, &op,
776*95b482a8SLen Brown 								AE_OK);
777*95b482a8SLen Brown 					if (ACPI_FAILURE(status)) {
778*95b482a8SLen Brown 						return_ACPI_STATUS(status);
779*95b482a8SLen Brown 					}
780*95b482a8SLen Brown 				}
781*95b482a8SLen Brown 
782*95b482a8SLen Brown 				if (status == AE_CTRL_TERMINATE) {
783*95b482a8SLen Brown 					status = AE_OK;
784*95b482a8SLen Brown 
785*95b482a8SLen Brown 					/* Clean up */
786*95b482a8SLen Brown 					do {
787*95b482a8SLen Brown 						if (op) {
788*95b482a8SLen Brown 							status2 =
789*95b482a8SLen Brown 							    acpi_ps_complete_this_op
790*95b482a8SLen Brown 							    (walk_state, op);
791*95b482a8SLen Brown 							if (ACPI_FAILURE
792*95b482a8SLen Brown 							    (status2)) {
793*95b482a8SLen Brown 								return_ACPI_STATUS
794*95b482a8SLen Brown 								    (status2);
795*95b482a8SLen Brown 							}
796*95b482a8SLen Brown 						}
797*95b482a8SLen Brown 
798*95b482a8SLen Brown 						acpi_ps_pop_scope(&
799*95b482a8SLen Brown 								  (walk_state->
800*95b482a8SLen Brown 								   parser_state),
801*95b482a8SLen Brown 								  &op,
802*95b482a8SLen Brown 								  &walk_state->
803*95b482a8SLen Brown 								  arg_types,
804*95b482a8SLen Brown 								  &walk_state->
805*95b482a8SLen Brown 								  arg_count);
806*95b482a8SLen Brown 
807*95b482a8SLen Brown 					} while (op);
808*95b482a8SLen Brown 
809*95b482a8SLen Brown 					return_ACPI_STATUS(status);
810*95b482a8SLen Brown 				}
811*95b482a8SLen Brown 
812*95b482a8SLen Brown 				else if (ACPI_FAILURE(status)) {
813*95b482a8SLen Brown 
814*95b482a8SLen Brown 					/* First error is most important */
815*95b482a8SLen Brown 
816*95b482a8SLen Brown 					(void)
817*95b482a8SLen Brown 					    acpi_ps_complete_this_op(walk_state,
818*95b482a8SLen Brown 								     op);
819*95b482a8SLen Brown 					return_ACPI_STATUS(status);
820*95b482a8SLen Brown 				}
821*95b482a8SLen Brown 			}
822*95b482a8SLen Brown 
823*95b482a8SLen Brown 			status2 = acpi_ps_complete_this_op(walk_state, op);
824*95b482a8SLen Brown 			if (ACPI_FAILURE(status2)) {
825*95b482a8SLen Brown 				return_ACPI_STATUS(status2);
826*95b482a8SLen Brown 			}
827*95b482a8SLen Brown 		}
828*95b482a8SLen Brown 
829*95b482a8SLen Brown 		acpi_ps_pop_scope(&(walk_state->parser_state), &op,
830*95b482a8SLen Brown 				  &walk_state->arg_types,
831*95b482a8SLen Brown 				  &walk_state->arg_count);
832*95b482a8SLen Brown 
833*95b482a8SLen Brown 	} while (op);
834*95b482a8SLen Brown 
835*95b482a8SLen Brown 	return_ACPI_STATUS(status);
836*95b482a8SLen Brown }
837*95b482a8SLen Brown 
838*95b482a8SLen Brown /*******************************************************************************
839*95b482a8SLen Brown  *
840*95b482a8SLen Brown  * FUNCTION:    acpi_ps_parse_loop
841*95b482a8SLen Brown  *
842*95b482a8SLen Brown  * PARAMETERS:  walk_state          - Current state
843*95b482a8SLen Brown  *
844*95b482a8SLen Brown  * RETURN:      Status
845*95b482a8SLen Brown  *
846*95b482a8SLen Brown  * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
847*95b482a8SLen Brown  *              a tree of ops.
848*95b482a8SLen Brown  *
849*95b482a8SLen Brown  ******************************************************************************/
850*95b482a8SLen Brown 
851*95b482a8SLen Brown acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
852*95b482a8SLen Brown {
853*95b482a8SLen Brown 	acpi_status status = AE_OK;
854*95b482a8SLen Brown 	union acpi_parse_object *op = NULL;	/* current op */
855*95b482a8SLen Brown 	struct acpi_parse_state *parser_state;
856*95b482a8SLen Brown 	u8 *aml_op_start = NULL;
857*95b482a8SLen Brown 
858*95b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
859*95b482a8SLen Brown 
860*95b482a8SLen Brown 	if (walk_state->descending_callback == NULL) {
861*95b482a8SLen Brown 		return_ACPI_STATUS(AE_BAD_PARAMETER);
862*95b482a8SLen Brown 	}
863*95b482a8SLen Brown 
864*95b482a8SLen Brown 	parser_state = &walk_state->parser_state;
865*95b482a8SLen Brown 	walk_state->arg_types = 0;
866*95b482a8SLen Brown 
867*95b482a8SLen Brown #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
868*95b482a8SLen Brown 
869*95b482a8SLen Brown 	if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
870*95b482a8SLen Brown 
871*95b482a8SLen Brown 		/* We are restarting a preempted control method */
872*95b482a8SLen Brown 
873*95b482a8SLen Brown 		if (acpi_ps_has_completed_scope(parser_state)) {
874*95b482a8SLen Brown 			/*
875*95b482a8SLen Brown 			 * We must check if a predicate to an IF or WHILE statement
876*95b482a8SLen Brown 			 * was just completed
877*95b482a8SLen Brown 			 */
878*95b482a8SLen Brown 			if ((parser_state->scope->parse_scope.op) &&
879*95b482a8SLen Brown 			    ((parser_state->scope->parse_scope.op->common.
880*95b482a8SLen Brown 			      aml_opcode == AML_IF_OP)
881*95b482a8SLen Brown 			     || (parser_state->scope->parse_scope.op->common.
882*95b482a8SLen Brown 				 aml_opcode == AML_WHILE_OP))
883*95b482a8SLen Brown 			    && (walk_state->control_state)
884*95b482a8SLen Brown 			    && (walk_state->control_state->common.state ==
885*95b482a8SLen Brown 				ACPI_CONTROL_PREDICATE_EXECUTING)) {
886*95b482a8SLen Brown 				/*
887*95b482a8SLen Brown 				 * A predicate was just completed, get the value of the
888*95b482a8SLen Brown 				 * predicate and branch based on that value
889*95b482a8SLen Brown 				 */
890*95b482a8SLen Brown 				walk_state->op = NULL;
891*95b482a8SLen Brown 				status =
892*95b482a8SLen Brown 				    acpi_ds_get_predicate_value(walk_state,
893*95b482a8SLen Brown 								ACPI_TO_POINTER
894*95b482a8SLen Brown 								(TRUE));
895*95b482a8SLen Brown 				if (ACPI_FAILURE(status)
896*95b482a8SLen Brown 				    && ((status & AE_CODE_MASK) !=
897*95b482a8SLen Brown 					AE_CODE_CONTROL)) {
898*95b482a8SLen Brown 					if (status == AE_AML_NO_RETURN_VALUE) {
899*95b482a8SLen Brown 						ACPI_EXCEPTION((AE_INFO, status,
900*95b482a8SLen Brown 								"Invoked method did not return a value"));
901*95b482a8SLen Brown 
902*95b482a8SLen Brown 					}
903*95b482a8SLen Brown 
904*95b482a8SLen Brown 					ACPI_EXCEPTION((AE_INFO, status,
905*95b482a8SLen Brown 							"GetPredicate Failed"));
906*95b482a8SLen Brown 					return_ACPI_STATUS(status);
907*95b482a8SLen Brown 				}
908*95b482a8SLen Brown 
909*95b482a8SLen Brown 				status =
910*95b482a8SLen Brown 				    acpi_ps_next_parse_state(walk_state, op,
911*95b482a8SLen Brown 							     status);
912*95b482a8SLen Brown 			}
913*95b482a8SLen Brown 
914*95b482a8SLen Brown 			acpi_ps_pop_scope(parser_state, &op,
915*95b482a8SLen Brown 					  &walk_state->arg_types,
916*95b482a8SLen Brown 					  &walk_state->arg_count);
917*95b482a8SLen Brown 			ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
918*95b482a8SLen Brown 					  "Popped scope, Op=%p\n", op));
919*95b482a8SLen Brown 		} else if (walk_state->prev_op) {
920*95b482a8SLen Brown 
921*95b482a8SLen Brown 			/* We were in the middle of an op */
922*95b482a8SLen Brown 
923*95b482a8SLen Brown 			op = walk_state->prev_op;
924*95b482a8SLen Brown 			walk_state->arg_types = walk_state->prev_arg_types;
925*95b482a8SLen Brown 		}
926*95b482a8SLen Brown 	}
927*95b482a8SLen Brown #endif
928*95b482a8SLen Brown 
929*95b482a8SLen Brown 	/* Iterative parsing loop, while there is more AML to process: */
930*95b482a8SLen Brown 
931*95b482a8SLen Brown 	while ((parser_state->aml < parser_state->aml_end) || (op)) {
932*95b482a8SLen Brown 		aml_op_start = parser_state->aml;
933*95b482a8SLen Brown 		if (!op) {
934*95b482a8SLen Brown 			status =
935*95b482a8SLen Brown 			    acpi_ps_create_op(walk_state, aml_op_start, &op);
936*95b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
937*95b482a8SLen Brown 				if (status == AE_CTRL_PARSE_CONTINUE) {
938*95b482a8SLen Brown 					continue;
939*95b482a8SLen Brown 				}
940*95b482a8SLen Brown 
941*95b482a8SLen Brown 				if (status == AE_CTRL_PARSE_PENDING) {
942*95b482a8SLen Brown 					status = AE_OK;
943*95b482a8SLen Brown 				}
944*95b482a8SLen Brown 
945*95b482a8SLen Brown 				status =
946*95b482a8SLen Brown 				    acpi_ps_complete_op(walk_state, &op,
947*95b482a8SLen Brown 							status);
948*95b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
949*95b482a8SLen Brown 					return_ACPI_STATUS(status);
950*95b482a8SLen Brown 				}
951*95b482a8SLen Brown 
952*95b482a8SLen Brown 				continue;
953*95b482a8SLen Brown 			}
954*95b482a8SLen Brown 
955*95b482a8SLen Brown 			op->common.aml_offset = walk_state->aml_offset;
956*95b482a8SLen Brown 
957*95b482a8SLen Brown 			if (walk_state->op_info) {
958*95b482a8SLen Brown 				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
959*95b482a8SLen Brown 						  "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",
960*95b482a8SLen Brown 						  (u32) op->common.aml_opcode,
961*95b482a8SLen Brown 						  walk_state->op_info->name, op,
962*95b482a8SLen Brown 						  parser_state->aml,
963*95b482a8SLen Brown 						  op->common.aml_offset));
964*95b482a8SLen Brown 			}
965*95b482a8SLen Brown 		}
966*95b482a8SLen Brown 
967*95b482a8SLen Brown 		/*
968*95b482a8SLen Brown 		 * Start arg_count at zero because we don't know if there are
969*95b482a8SLen Brown 		 * any args yet
970*95b482a8SLen Brown 		 */
971*95b482a8SLen Brown 		walk_state->arg_count = 0;
972*95b482a8SLen Brown 
973*95b482a8SLen Brown 		/* Are there any arguments that must be processed? */
974*95b482a8SLen Brown 
975*95b482a8SLen Brown 		if (walk_state->arg_types) {
976*95b482a8SLen Brown 
977*95b482a8SLen Brown 			/* Get arguments */
978*95b482a8SLen Brown 
979*95b482a8SLen Brown 			status =
980*95b482a8SLen Brown 			    acpi_ps_get_arguments(walk_state, aml_op_start, op);
981*95b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
982*95b482a8SLen Brown 				status =
983*95b482a8SLen Brown 				    acpi_ps_complete_op(walk_state, &op,
984*95b482a8SLen Brown 							status);
985*95b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
986*95b482a8SLen Brown 					return_ACPI_STATUS(status);
987*95b482a8SLen Brown 				}
988*95b482a8SLen Brown 
989*95b482a8SLen Brown 				continue;
990*95b482a8SLen Brown 			}
991*95b482a8SLen Brown 		}
992*95b482a8SLen Brown 
993*95b482a8SLen Brown 		/* Check for arguments that need to be processed */
994*95b482a8SLen Brown 
995*95b482a8SLen Brown 		if (walk_state->arg_count) {
996*95b482a8SLen Brown 			/*
997*95b482a8SLen Brown 			 * There are arguments (complex ones), push Op and
998*95b482a8SLen Brown 			 * prepare for argument
999*95b482a8SLen Brown 			 */
1000*95b482a8SLen Brown 			status = acpi_ps_push_scope(parser_state, op,
1001*95b482a8SLen Brown 						    walk_state->arg_types,
1002*95b482a8SLen Brown 						    walk_state->arg_count);
1003*95b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
1004*95b482a8SLen Brown 				status =
1005*95b482a8SLen Brown 				    acpi_ps_complete_op(walk_state, &op,
1006*95b482a8SLen Brown 							status);
1007*95b482a8SLen Brown 				if (ACPI_FAILURE(status)) {
1008*95b482a8SLen Brown 					return_ACPI_STATUS(status);
1009*95b482a8SLen Brown 				}
1010*95b482a8SLen Brown 
1011*95b482a8SLen Brown 				continue;
1012*95b482a8SLen Brown 			}
1013*95b482a8SLen Brown 
1014*95b482a8SLen Brown 			op = NULL;
1015*95b482a8SLen Brown 			continue;
1016*95b482a8SLen Brown 		}
1017*95b482a8SLen Brown 
1018*95b482a8SLen Brown 		/*
1019*95b482a8SLen Brown 		 * All arguments have been processed -- Op is complete,
1020*95b482a8SLen Brown 		 * prepare for next
1021*95b482a8SLen Brown 		 */
1022*95b482a8SLen Brown 		walk_state->op_info =
1023*95b482a8SLen Brown 		    acpi_ps_get_opcode_info(op->common.aml_opcode);
1024*95b482a8SLen Brown 		if (walk_state->op_info->flags & AML_NAMED) {
1025*95b482a8SLen Brown 			if (acpi_gbl_depth) {
1026*95b482a8SLen Brown 				acpi_gbl_depth--;
1027*95b482a8SLen Brown 			}
1028*95b482a8SLen Brown 
1029*95b482a8SLen Brown 			if (op->common.aml_opcode == AML_REGION_OP ||
1030*95b482a8SLen Brown 			    op->common.aml_opcode == AML_DATA_REGION_OP) {
1031*95b482a8SLen Brown 				/*
1032*95b482a8SLen Brown 				 * Skip parsing of control method or opregion body,
1033*95b482a8SLen Brown 				 * because we don't have enough info in the first pass
1034*95b482a8SLen Brown 				 * to parse them correctly.
1035*95b482a8SLen Brown 				 *
1036*95b482a8SLen Brown 				 * Completed parsing an op_region declaration, we now
1037*95b482a8SLen Brown 				 * know the length.
1038*95b482a8SLen Brown 				 */
1039*95b482a8SLen Brown 				op->named.length =
1040*95b482a8SLen Brown 				    (u32) (parser_state->aml - op->named.data);
1041*95b482a8SLen Brown 			}
1042*95b482a8SLen Brown 		}
1043*95b482a8SLen Brown 
1044*95b482a8SLen Brown 		if (walk_state->op_info->flags & AML_CREATE) {
1045*95b482a8SLen Brown 			/*
1046*95b482a8SLen Brown 			 * Backup to beginning of create_xXXfield declaration (1 for
1047*95b482a8SLen Brown 			 * Opcode)
1048*95b482a8SLen Brown 			 *
1049*95b482a8SLen Brown 			 * body_length is unknown until we parse the body
1050*95b482a8SLen Brown 			 */
1051*95b482a8SLen Brown 			op->named.length =
1052*95b482a8SLen Brown 			    (u32) (parser_state->aml - op->named.data);
1053*95b482a8SLen Brown 		}
1054*95b482a8SLen Brown 
1055*95b482a8SLen Brown 		if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
1056*95b482a8SLen Brown 			/*
1057*95b482a8SLen Brown 			 * Backup to beginning of bank_field declaration
1058*95b482a8SLen Brown 			 *
1059*95b482a8SLen Brown 			 * body_length is unknown until we parse the body
1060*95b482a8SLen Brown 			 */
1061*95b482a8SLen Brown 			op->named.length =
1062*95b482a8SLen Brown 			    (u32) (parser_state->aml - op->named.data);
1063*95b482a8SLen Brown 		}
1064*95b482a8SLen Brown 
1065*95b482a8SLen Brown 		/* This op complete, notify the dispatcher */
1066*95b482a8SLen Brown 
1067*95b482a8SLen Brown 		if (walk_state->ascending_callback != NULL) {
1068*95b482a8SLen Brown 			walk_state->op = op;
1069*95b482a8SLen Brown 			walk_state->opcode = op->common.aml_opcode;
1070*95b482a8SLen Brown 
1071*95b482a8SLen Brown 			status = walk_state->ascending_callback(walk_state);
1072*95b482a8SLen Brown 			status =
1073*95b482a8SLen Brown 			    acpi_ps_next_parse_state(walk_state, op, status);
1074*95b482a8SLen Brown 			if (status == AE_CTRL_PENDING) {
1075*95b482a8SLen Brown 				status = AE_OK;
1076*95b482a8SLen Brown 			}
1077*95b482a8SLen Brown 		}
1078*95b482a8SLen Brown 
1079*95b482a8SLen Brown 		status = acpi_ps_complete_op(walk_state, &op, status);
1080*95b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
1081*95b482a8SLen Brown 			return_ACPI_STATUS(status);
1082*95b482a8SLen Brown 		}
1083*95b482a8SLen Brown 
1084*95b482a8SLen Brown 	}			/* while parser_state->Aml */
1085*95b482a8SLen Brown 
1086*95b482a8SLen Brown 	status = acpi_ps_complete_final_op(walk_state, op, status);
1087*95b482a8SLen Brown 	return_ACPI_STATUS(status);
1088*95b482a8SLen Brown }
1089