xref: /openbmc/linux/drivers/acpi/acpica/psloop.c (revision d8bcaabe)
1 /******************************************************************************
2  *
3  * Module Name: psloop - Main AML parse loop
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, Intel Corp.
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  * Parse the AML and build an operation tree as most interpreters, (such as
46  * Perl) do. Parsing is done by hand rather than with a YACC generated parser
47  * to tightly constrain stack and dynamic memory usage. Parsing is kept
48  * flexible and the code fairly compact by parsing based on a list of AML
49  * opcode templates in aml_op_info[].
50  */
51 
52 #include <acpi/acpi.h>
53 #include "accommon.h"
54 #include "acinterp.h"
55 #include "acparser.h"
56 #include "acdispat.h"
57 #include "amlcode.h"
58 #include "acconvert.h"
59 
60 #define _COMPONENT          ACPI_PARSER
61 ACPI_MODULE_NAME("psloop")
62 
63 /* Local prototypes */
64 static acpi_status
65 acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
66 		      u8 * aml_op_start, union acpi_parse_object *op);
67 
68 static void
69 acpi_ps_link_module_code(union acpi_parse_object *parent_op,
70 			 u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
71 
72 /*******************************************************************************
73  *
74  * FUNCTION:    acpi_ps_get_arguments
75  *
76  * PARAMETERS:  walk_state          - Current state
77  *              aml_op_start        - Op start in AML
78  *              op                  - Current Op
79  *
80  * RETURN:      Status
81  *
82  * DESCRIPTION: Get arguments for passed Op.
83  *
84  ******************************************************************************/
85 
86 static acpi_status
87 acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
88 		      u8 * aml_op_start, union acpi_parse_object *op)
89 {
90 	acpi_status status = AE_OK;
91 	union acpi_parse_object *arg = NULL;
92 	const struct acpi_opcode_info *op_info;
93 
94 	ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
95 
96 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
97 			  "Get arguments for opcode [%s]\n",
98 			  op->common.aml_op_name));
99 
100 	switch (op->common.aml_opcode) {
101 	case AML_BYTE_OP:	/* AML_BYTEDATA_ARG */
102 	case AML_WORD_OP:	/* AML_WORDDATA_ARG */
103 	case AML_DWORD_OP:	/* AML_DWORDATA_ARG */
104 	case AML_QWORD_OP:	/* AML_QWORDATA_ARG */
105 	case AML_STRING_OP:	/* AML_ASCIICHARLIST_ARG */
106 
107 		/* Fill in constant or string argument directly */
108 
109 		acpi_ps_get_next_simple_arg(&(walk_state->parser_state),
110 					    GET_CURRENT_ARG_TYPE(walk_state->
111 								 arg_types),
112 					    op);
113 		break;
114 
115 	case AML_INT_NAMEPATH_OP:	/* AML_NAMESTRING_ARG */
116 
117 		status = acpi_ps_get_next_namepath(walk_state,
118 						   &(walk_state->parser_state),
119 						   op,
120 						   ACPI_POSSIBLE_METHOD_CALL);
121 		if (ACPI_FAILURE(status)) {
122 			return_ACPI_STATUS(status);
123 		}
124 
125 		walk_state->arg_types = 0;
126 		break;
127 
128 	default:
129 		/*
130 		 * Op is not a constant or string, append each argument to the Op
131 		 */
132 		while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
133 		       !walk_state->arg_count) {
134 			walk_state->aml = walk_state->parser_state.aml;
135 
136 			switch (op->common.aml_opcode) {
137 			case AML_METHOD_OP:
138 			case AML_BUFFER_OP:
139 			case AML_PACKAGE_OP:
140 			case AML_VARIABLE_PACKAGE_OP:
141 			case AML_WHILE_OP:
142 
143 				break;
144 
145 			default:
146 
147 				ASL_CV_CAPTURE_COMMENTS(walk_state);
148 				break;
149 			}
150 
151 			status =
152 			    acpi_ps_get_next_arg(walk_state,
153 						 &(walk_state->parser_state),
154 						 GET_CURRENT_ARG_TYPE
155 						 (walk_state->arg_types), &arg);
156 			if (ACPI_FAILURE(status)) {
157 				return_ACPI_STATUS(status);
158 			}
159 
160 			if (arg) {
161 				acpi_ps_append_arg(op, arg);
162 			}
163 
164 			INCREMENT_ARG_LIST(walk_state->arg_types);
165 		}
166 
167 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
168 				  "Final argument count: %u pass %u\n",
169 				  walk_state->arg_count,
170 				  walk_state->pass_number));
171 
172 		/*
173 		 * Handle executable code at "module-level". This refers to
174 		 * executable opcodes that appear outside of any control method.
175 		 */
176 		if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
177 		    ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
178 			/*
179 			 * We want to skip If/Else/While constructs during Pass1 because we
180 			 * want to actually conditionally execute the code during Pass2.
181 			 *
182 			 * Except for disassembly, where we always want to walk the
183 			 * If/Else/While packages
184 			 */
185 			switch (op->common.aml_opcode) {
186 			case AML_IF_OP:
187 			case AML_ELSE_OP:
188 			case AML_WHILE_OP:
189 				/*
190 				 * Currently supported module-level opcodes are:
191 				 * IF/ELSE/WHILE. These appear to be the most common,
192 				 * and easiest to support since they open an AML
193 				 * package.
194 				 */
195 				if (walk_state->pass_number ==
196 				    ACPI_IMODE_LOAD_PASS1) {
197 					acpi_ps_link_module_code(op->common.
198 								 parent,
199 								 aml_op_start,
200 								 (u32)
201 								 (walk_state->
202 								 parser_state.
203 								 pkg_end -
204 								 aml_op_start),
205 								 walk_state->
206 								 owner_id);
207 				}
208 
209 				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
210 						  "Pass1: Skipping an If/Else/While body\n"));
211 
212 				/* Skip body of if/else/while in pass 1 */
213 
214 				walk_state->parser_state.aml =
215 				    walk_state->parser_state.pkg_end;
216 				walk_state->arg_count = 0;
217 				break;
218 
219 			default:
220 				/*
221 				 * Check for an unsupported executable opcode at module
222 				 * level. We must be in PASS1, the parent must be a SCOPE,
223 				 * The opcode class must be EXECUTE, and the opcode must
224 				 * not be an argument to another opcode.
225 				 */
226 				if ((walk_state->pass_number ==
227 				     ACPI_IMODE_LOAD_PASS1)
228 				    && (op->common.parent->common.aml_opcode ==
229 					AML_SCOPE_OP)) {
230 					op_info =
231 					    acpi_ps_get_opcode_info(op->common.
232 								    aml_opcode);
233 					if ((op_info->class ==
234 					     AML_CLASS_EXECUTE) && (!arg)) {
235 						ACPI_WARNING((AE_INFO,
236 							      "Unsupported module-level executable opcode "
237 							      "0x%.2X at table offset 0x%.4X",
238 							      op->common.
239 							      aml_opcode,
240 							      (u32)
241 							      (ACPI_PTR_DIFF
242 							       (aml_op_start,
243 								walk_state->
244 								parser_state.
245 								aml_start) +
246 							       sizeof(struct
247 								      acpi_table_header))));
248 					}
249 				}
250 				break;
251 			}
252 		}
253 
254 		/* Special processing for certain opcodes */
255 
256 		switch (op->common.aml_opcode) {
257 		case AML_METHOD_OP:
258 			/*
259 			 * Skip parsing of control method because we don't have enough
260 			 * info in the first pass to parse it correctly.
261 			 *
262 			 * Save the length and address of the body
263 			 */
264 			op->named.data = walk_state->parser_state.aml;
265 			op->named.length = (u32)
266 			    (walk_state->parser_state.pkg_end -
267 			     walk_state->parser_state.aml);
268 
269 			/* Skip body of method */
270 
271 			walk_state->parser_state.aml =
272 			    walk_state->parser_state.pkg_end;
273 			walk_state->arg_count = 0;
274 			break;
275 
276 		case AML_BUFFER_OP:
277 		case AML_PACKAGE_OP:
278 		case AML_VARIABLE_PACKAGE_OP:
279 
280 			if ((op->common.parent) &&
281 			    (op->common.parent->common.aml_opcode ==
282 			     AML_NAME_OP)
283 			    && (walk_state->pass_number <=
284 				ACPI_IMODE_LOAD_PASS2)) {
285 				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
286 						  "Setup Package/Buffer: Pass %u, AML Ptr: %p\n",
287 						  walk_state->pass_number,
288 						  aml_op_start));
289 
290 				/*
291 				 * Skip parsing of Buffers and Packages because we don't have
292 				 * enough info in the first pass to parse them correctly.
293 				 */
294 				op->named.data = aml_op_start;
295 				op->named.length = (u32)
296 				    (walk_state->parser_state.pkg_end -
297 				     aml_op_start);
298 
299 				/* Skip body */
300 
301 				walk_state->parser_state.aml =
302 				    walk_state->parser_state.pkg_end;
303 				walk_state->arg_count = 0;
304 			}
305 			break;
306 
307 		case AML_WHILE_OP:
308 
309 			if (walk_state->control_state) {
310 				walk_state->control_state->control.package_end =
311 				    walk_state->parser_state.pkg_end;
312 			}
313 			break;
314 
315 		default:
316 
317 			/* No action for all other opcodes */
318 
319 			break;
320 		}
321 
322 		break;
323 	}
324 
325 	return_ACPI_STATUS(AE_OK);
326 }
327 
328 /*******************************************************************************
329  *
330  * FUNCTION:    acpi_ps_link_module_code
331  *
332  * PARAMETERS:  parent_op           - Parent parser op
333  *              aml_start           - Pointer to the AML
334  *              aml_length          - Length of executable AML
335  *              owner_id            - owner_id of module level code
336  *
337  * RETURN:      None.
338  *
339  * DESCRIPTION: Wrap the module-level code with a method object and link the
340  *              object to the global list. Note, the mutex field of the method
341  *              object is used to link multiple module-level code objects.
342  *
343  ******************************************************************************/
344 
345 static void
346 acpi_ps_link_module_code(union acpi_parse_object *parent_op,
347 			 u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
348 {
349 	union acpi_operand_object *prev;
350 	union acpi_operand_object *next;
351 	union acpi_operand_object *method_obj;
352 	struct acpi_namespace_node *parent_node;
353 
354 	ACPI_FUNCTION_TRACE(ps_link_module_code);
355 
356 	/* Get the tail of the list */
357 
358 	prev = next = acpi_gbl_module_code_list;
359 	while (next) {
360 		prev = next;
361 		next = next->method.mutex;
362 	}
363 
364 	/*
365 	 * Insert the module level code into the list. Merge it if it is
366 	 * adjacent to the previous element.
367 	 */
368 	if (!prev ||
369 	    ((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
370 
371 		/* Create, initialize, and link a new temporary method object */
372 
373 		method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
374 		if (!method_obj) {
375 			return_VOID;
376 		}
377 
378 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
379 				  "Create/Link new code block: %p\n",
380 				  method_obj));
381 
382 		if (parent_op->common.node) {
383 			parent_node = parent_op->common.node;
384 		} else {
385 			parent_node = acpi_gbl_root_node;
386 		}
387 
388 		method_obj->method.aml_start = aml_start;
389 		method_obj->method.aml_length = aml_length;
390 		method_obj->method.owner_id = owner_id;
391 		method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
392 
393 		/*
394 		 * Save the parent node in next_object. This is cheating, but we
395 		 * don't want to expand the method object.
396 		 */
397 		method_obj->method.next_object =
398 		    ACPI_CAST_PTR(union acpi_operand_object, parent_node);
399 
400 		if (!prev) {
401 			acpi_gbl_module_code_list = method_obj;
402 		} else {
403 			prev->method.mutex = method_obj;
404 		}
405 	} else {
406 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
407 				  "Appending to existing code block: %p\n",
408 				  prev));
409 
410 		prev->method.aml_length += aml_length;
411 	}
412 
413 	return_VOID;
414 }
415 
416 /*******************************************************************************
417  *
418  * FUNCTION:    acpi_ps_parse_loop
419  *
420  * PARAMETERS:  walk_state          - Current state
421  *
422  * RETURN:      Status
423  *
424  * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
425  *              a tree of ops.
426  *
427  ******************************************************************************/
428 
429 acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
430 {
431 	acpi_status status = AE_OK;
432 	union acpi_parse_object *op = NULL;	/* current op */
433 	struct acpi_parse_state *parser_state;
434 	u8 *aml_op_start = NULL;
435 
436 	ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
437 
438 	if (walk_state->descending_callback == NULL) {
439 		return_ACPI_STATUS(AE_BAD_PARAMETER);
440 	}
441 
442 	parser_state = &walk_state->parser_state;
443 	walk_state->arg_types = 0;
444 
445 #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
446 
447 	if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
448 
449 		/* We are restarting a preempted control method */
450 
451 		if (acpi_ps_has_completed_scope(parser_state)) {
452 			/*
453 			 * We must check if a predicate to an IF or WHILE statement
454 			 * was just completed
455 			 */
456 			if ((parser_state->scope->parse_scope.op) &&
457 			    ((parser_state->scope->parse_scope.op->common.
458 			      aml_opcode == AML_IF_OP)
459 			     || (parser_state->scope->parse_scope.op->common.
460 				 aml_opcode == AML_WHILE_OP))
461 			    && (walk_state->control_state)
462 			    && (walk_state->control_state->common.state ==
463 				ACPI_CONTROL_PREDICATE_EXECUTING)) {
464 				/*
465 				 * A predicate was just completed, get the value of the
466 				 * predicate and branch based on that value
467 				 */
468 				walk_state->op = NULL;
469 				status =
470 				    acpi_ds_get_predicate_value(walk_state,
471 								ACPI_TO_POINTER
472 								(TRUE));
473 				if (ACPI_FAILURE(status)
474 				    && ((status & AE_CODE_MASK) !=
475 					AE_CODE_CONTROL)) {
476 					if (status == AE_AML_NO_RETURN_VALUE) {
477 						ACPI_EXCEPTION((AE_INFO, status,
478 								"Invoked method did not return a value"));
479 					}
480 
481 					ACPI_EXCEPTION((AE_INFO, status,
482 							"GetPredicate Failed"));
483 					return_ACPI_STATUS(status);
484 				}
485 
486 				status =
487 				    acpi_ps_next_parse_state(walk_state, op,
488 							     status);
489 			}
490 
491 			acpi_ps_pop_scope(parser_state, &op,
492 					  &walk_state->arg_types,
493 					  &walk_state->arg_count);
494 			ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
495 					  "Popped scope, Op=%p\n", op));
496 		} else if (walk_state->prev_op) {
497 
498 			/* We were in the middle of an op */
499 
500 			op = walk_state->prev_op;
501 			walk_state->arg_types = walk_state->prev_arg_types;
502 		}
503 	}
504 #endif
505 
506 	/* Iterative parsing loop, while there is more AML to process: */
507 
508 	while ((parser_state->aml < parser_state->aml_end) || (op)) {
509 		ASL_CV_CAPTURE_COMMENTS(walk_state);
510 
511 		aml_op_start = parser_state->aml;
512 		if (!op) {
513 			status =
514 			    acpi_ps_create_op(walk_state, aml_op_start, &op);
515 			if (ACPI_FAILURE(status)) {
516 				if (status == AE_CTRL_PARSE_CONTINUE) {
517 					continue;
518 				}
519 
520 				if (status == AE_CTRL_PARSE_PENDING) {
521 					status = AE_OK;
522 				}
523 
524 				if (status == AE_CTRL_TERMINATE) {
525 					return_ACPI_STATUS(status);
526 				}
527 
528 				status =
529 				    acpi_ps_complete_op(walk_state, &op,
530 							status);
531 				if (ACPI_FAILURE(status)) {
532 					return_ACPI_STATUS(status);
533 				}
534 
535 				continue;
536 			}
537 
538 			acpi_ex_start_trace_opcode(op, walk_state);
539 		}
540 
541 		/*
542 		 * Start arg_count at zero because we don't know if there are
543 		 * any args yet
544 		 */
545 		walk_state->arg_count = 0;
546 
547 		switch (op->common.aml_opcode) {
548 		case AML_BYTE_OP:
549 		case AML_WORD_OP:
550 		case AML_DWORD_OP:
551 		case AML_QWORD_OP:
552 
553 			break;
554 
555 		default:
556 
557 			ASL_CV_CAPTURE_COMMENTS(walk_state);
558 			break;
559 		}
560 
561 		/* Are there any arguments that must be processed? */
562 
563 		if (walk_state->arg_types) {
564 
565 			/* Get arguments */
566 
567 			status =
568 			    acpi_ps_get_arguments(walk_state, aml_op_start, op);
569 			if (ACPI_FAILURE(status)) {
570 				status =
571 				    acpi_ps_complete_op(walk_state, &op,
572 							status);
573 				if (ACPI_FAILURE(status)) {
574 					return_ACPI_STATUS(status);
575 				}
576 
577 				continue;
578 			}
579 		}
580 
581 		/* Check for arguments that need to be processed */
582 
583 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
584 				  "Parseloop: argument count: %u\n",
585 				  walk_state->arg_count));
586 
587 		if (walk_state->arg_count) {
588 			/*
589 			 * There are arguments (complex ones), push Op and
590 			 * prepare for argument
591 			 */
592 			status = acpi_ps_push_scope(parser_state, op,
593 						    walk_state->arg_types,
594 						    walk_state->arg_count);
595 			if (ACPI_FAILURE(status)) {
596 				status =
597 				    acpi_ps_complete_op(walk_state, &op,
598 							status);
599 				if (ACPI_FAILURE(status)) {
600 					return_ACPI_STATUS(status);
601 				}
602 
603 				continue;
604 			}
605 
606 			op = NULL;
607 			continue;
608 		}
609 
610 		/*
611 		 * All arguments have been processed -- Op is complete,
612 		 * prepare for next
613 		 */
614 		walk_state->op_info =
615 		    acpi_ps_get_opcode_info(op->common.aml_opcode);
616 		if (walk_state->op_info->flags & AML_NAMED) {
617 			if (op->common.aml_opcode == AML_REGION_OP ||
618 			    op->common.aml_opcode == AML_DATA_REGION_OP) {
619 				/*
620 				 * Skip parsing of control method or opregion body,
621 				 * because we don't have enough info in the first pass
622 				 * to parse them correctly.
623 				 *
624 				 * Completed parsing an op_region declaration, we now
625 				 * know the length.
626 				 */
627 				op->named.length =
628 				    (u32) (parser_state->aml - op->named.data);
629 			}
630 		}
631 
632 		if (walk_state->op_info->flags & AML_CREATE) {
633 			/*
634 			 * Backup to beginning of create_XXXfield declaration (1 for
635 			 * Opcode)
636 			 *
637 			 * body_length is unknown until we parse the body
638 			 */
639 			op->named.length =
640 			    (u32) (parser_state->aml - op->named.data);
641 		}
642 
643 		if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
644 			/*
645 			 * Backup to beginning of bank_field declaration
646 			 *
647 			 * body_length is unknown until we parse the body
648 			 */
649 			op->named.length =
650 			    (u32) (parser_state->aml - op->named.data);
651 		}
652 
653 		/* This op complete, notify the dispatcher */
654 
655 		if (walk_state->ascending_callback != NULL) {
656 			walk_state->op = op;
657 			walk_state->opcode = op->common.aml_opcode;
658 
659 			status = walk_state->ascending_callback(walk_state);
660 			status =
661 			    acpi_ps_next_parse_state(walk_state, op, status);
662 			if (status == AE_CTRL_PENDING) {
663 				status = AE_OK;
664 			}
665 		}
666 
667 		status = acpi_ps_complete_op(walk_state, &op, status);
668 		if (ACPI_FAILURE(status)) {
669 			return_ACPI_STATUS(status);
670 		}
671 
672 	}			/* while parser_state->Aml */
673 
674 	status = acpi_ps_complete_final_op(walk_state, op, status);
675 	return_ACPI_STATUS(status);
676 }
677