• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Module Name: psobject - Support for parse objects
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48 
49 #define _COMPONENT          ACPI_PARSER
50 ACPI_MODULE_NAME("psobject")
51 
52 /* Local prototypes */
53 static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state);
54 
55 /*******************************************************************************
56  *
57  * FUNCTION:    acpi_ps_get_aml_opcode
58  *
59  * PARAMETERS:  walk_state          - Current state
60  *
61  * RETURN:      Status
62  *
63  * DESCRIPTION: Extract the next AML opcode from the input stream.
64  *
65  ******************************************************************************/
66 
acpi_ps_get_aml_opcode(struct acpi_walk_state * walk_state)67 static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state)
68 {
69 	u32 aml_offset;
70 
71 	ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state);
72 
73 	walk_state->aml = walk_state->parser_state.aml;
74 	walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state));
75 
76 	/*
77 	 * First cut to determine what we have found:
78 	 * 1) A valid AML opcode
79 	 * 2) A name string
80 	 * 3) An unknown/invalid opcode
81 	 */
82 	walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode);
83 
84 	switch (walk_state->op_info->class) {
85 	case AML_CLASS_ASCII:
86 	case AML_CLASS_PREFIX:
87 		/*
88 		 * Starts with a valid prefix or ASCII char, this is a name
89 		 * string. Convert the bare name string to a namepath.
90 		 */
91 		walk_state->opcode = AML_INT_NAMEPATH_OP;
92 		walk_state->arg_types = ARGP_NAMESTRING;
93 		break;
94 
95 	case AML_CLASS_UNKNOWN:
96 
97 		/* The opcode is unrecognized. Complain and skip unknown opcodes */
98 
99 		if (walk_state->pass_number == 2) {
100 			aml_offset = (u32)ACPI_PTR_DIFF(walk_state->aml,
101 							walk_state->
102 							parser_state.aml_start);
103 
104 			ACPI_ERROR((AE_INFO,
105 				    "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring",
106 				    walk_state->opcode,
107 				    (u32)(aml_offset +
108 					  sizeof(struct acpi_table_header))));
109 
110 			ACPI_DUMP_BUFFER((walk_state->parser_state.aml - 16),
111 					 48);
112 
113 #ifdef ACPI_ASL_COMPILER
114 			/*
115 			 * This is executed for the disassembler only. Output goes
116 			 * to the disassembled ASL output file.
117 			 */
118 			acpi_os_printf
119 			    ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n",
120 			     walk_state->opcode,
121 			     (u32)(aml_offset +
122 				   sizeof(struct acpi_table_header)));
123 
124 			ACPI_ERROR((AE_INFO,
125 				    "Aborting disassembly, AML byte code is corrupt"));
126 
127 			/* Dump the context surrounding the invalid opcode */
128 
129 			acpi_ut_dump_buffer(((u8 *)walk_state->parser_state.
130 					     aml - 16), 48, DB_BYTE_DISPLAY,
131 					    (aml_offset +
132 					     sizeof(struct acpi_table_header) -
133 					     16));
134 			acpi_os_printf(" */\n");
135 
136 			/*
137 			 * Just abort the disassembly, cannot continue because the
138 			 * parser is essentially lost. The disassembler can then
139 			 * randomly fail because an ill-constructed parse tree
140 			 * can result.
141 			 */
142 			return_ACPI_STATUS(AE_AML_BAD_OPCODE);
143 #endif
144 		}
145 
146 		/* Increment past one-byte or two-byte opcode */
147 
148 		walk_state->parser_state.aml++;
149 		if (walk_state->opcode > 0xFF) {	/* Can only happen if first byte is 0x5B */
150 			walk_state->parser_state.aml++;
151 		}
152 
153 		return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
154 
155 	default:
156 
157 		/* Found opcode info, this is a normal opcode */
158 
159 		walk_state->parser_state.aml +=
160 		    acpi_ps_get_opcode_size(walk_state->opcode);
161 		walk_state->arg_types = walk_state->op_info->parse_args;
162 		break;
163 	}
164 
165 	return_ACPI_STATUS(AE_OK);
166 }
167 
168 /*******************************************************************************
169  *
170  * FUNCTION:    acpi_ps_build_named_op
171  *
172  * PARAMETERS:  walk_state          - Current state
173  *              aml_op_start        - Begin of named Op in AML
174  *              unnamed_op          - Early Op (not a named Op)
175  *              op                  - Returned Op
176  *
177  * RETURN:      Status
178  *
179  * DESCRIPTION: Parse a named Op
180  *
181  ******************************************************************************/
182 
183 acpi_status
acpi_ps_build_named_op(struct acpi_walk_state * walk_state,u8 * aml_op_start,union acpi_parse_object * unnamed_op,union acpi_parse_object ** op)184 acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
185 		       u8 *aml_op_start,
186 		       union acpi_parse_object *unnamed_op,
187 		       union acpi_parse_object **op)
188 {
189 	acpi_status status = AE_OK;
190 	union acpi_parse_object *arg = NULL;
191 
192 	ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state);
193 
194 	unnamed_op->common.value.arg = NULL;
195 	unnamed_op->common.arg_list_length = 0;
196 	unnamed_op->common.aml_opcode = walk_state->opcode;
197 
198 	/*
199 	 * Get and append arguments until we find the node that contains
200 	 * the name (the type ARGP_NAME).
201 	 */
202 	while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
203 	       (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) {
204 		status =
205 		    acpi_ps_get_next_arg(walk_state,
206 					 &(walk_state->parser_state),
207 					 GET_CURRENT_ARG_TYPE(walk_state->
208 							      arg_types), &arg);
209 		if (ACPI_FAILURE(status)) {
210 			return_ACPI_STATUS(status);
211 		}
212 
213 		acpi_ps_append_arg(unnamed_op, arg);
214 		INCREMENT_ARG_LIST(walk_state->arg_types);
215 	}
216 
217 	/*
218 	 * Make sure that we found a NAME and didn't run out of arguments
219 	 */
220 	if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) {
221 		return_ACPI_STATUS(AE_AML_NO_OPERAND);
222 	}
223 
224 	/* We know that this arg is a name, move to next arg */
225 
226 	INCREMENT_ARG_LIST(walk_state->arg_types);
227 
228 	/*
229 	 * Find the object. This will either insert the object into
230 	 * the namespace or simply look it up
231 	 */
232 	walk_state->op = NULL;
233 
234 	status = walk_state->descending_callback(walk_state, op);
235 	if (ACPI_FAILURE(status)) {
236 		if (status != AE_CTRL_TERMINATE) {
237 			ACPI_EXCEPTION((AE_INFO, status,
238 					"During name lookup/catalog"));
239 		}
240 		return_ACPI_STATUS(status);
241 	}
242 
243 	if (!*op) {
244 		return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
245 	}
246 
247 	status = acpi_ps_next_parse_state(walk_state, *op, status);
248 	if (ACPI_FAILURE(status)) {
249 		if (status == AE_CTRL_PENDING) {
250 			status = AE_CTRL_PARSE_PENDING;
251 		}
252 		return_ACPI_STATUS(status);
253 	}
254 
255 	acpi_ps_append_arg(*op, unnamed_op->common.value.arg);
256 
257 	if ((*op)->common.aml_opcode == AML_REGION_OP ||
258 	    (*op)->common.aml_opcode == AML_DATA_REGION_OP) {
259 		/*
260 		 * Defer final parsing of an operation_region body, because we don't
261 		 * have enough info in the first pass to parse it correctly (i.e.,
262 		 * there may be method calls within the term_arg elements of the body.)
263 		 *
264 		 * However, we must continue parsing because the opregion is not a
265 		 * standalone package -- we don't know where the end is at this point.
266 		 *
267 		 * (Length is unknown until parse of the body complete)
268 		 */
269 		(*op)->named.data = aml_op_start;
270 		(*op)->named.length = 0;
271 	}
272 
273 	return_ACPI_STATUS(AE_OK);
274 }
275 
276 /*******************************************************************************
277  *
278  * FUNCTION:    acpi_ps_create_op
279  *
280  * PARAMETERS:  walk_state          - Current state
281  *              aml_op_start        - Op start in AML
282  *              new_op              - Returned Op
283  *
284  * RETURN:      Status
285  *
286  * DESCRIPTION: Get Op from AML
287  *
288  ******************************************************************************/
289 
290 acpi_status
acpi_ps_create_op(struct acpi_walk_state * walk_state,u8 * aml_op_start,union acpi_parse_object ** new_op)291 acpi_ps_create_op(struct acpi_walk_state *walk_state,
292 		  u8 *aml_op_start, union acpi_parse_object **new_op)
293 {
294 	acpi_status status = AE_OK;
295 	union acpi_parse_object *op;
296 	union acpi_parse_object *named_op = NULL;
297 	union acpi_parse_object *parent_scope;
298 	u8 argument_count;
299 	const struct acpi_opcode_info *op_info;
300 
301 	ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state);
302 
303 	status = acpi_ps_get_aml_opcode(walk_state);
304 	if (status == AE_CTRL_PARSE_CONTINUE) {
305 		return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
306 	}
307 	if (ACPI_FAILURE(status)) {
308 		return_ACPI_STATUS(status);
309 	}
310 
311 	/* Create Op structure and append to parent's argument list */
312 
313 	walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode);
314 	op = acpi_ps_alloc_op(walk_state->opcode, aml_op_start);
315 	if (!op) {
316 		return_ACPI_STATUS(AE_NO_MEMORY);
317 	}
318 
319 	if (walk_state->op_info->flags & AML_NAMED) {
320 		status =
321 		    acpi_ps_build_named_op(walk_state, aml_op_start, op,
322 					   &named_op);
323 		acpi_ps_free_op(op);
324 		if (ACPI_FAILURE(status)) {
325 			return_ACPI_STATUS(status);
326 		}
327 
328 		*new_op = named_op;
329 		return_ACPI_STATUS(AE_OK);
330 	}
331 
332 	/* Not a named opcode, just allocate Op and append to parent */
333 
334 	if (walk_state->op_info->flags & AML_CREATE) {
335 		/*
336 		 * Backup to beginning of create_XXXfield declaration
337 		 * body_length is unknown until we parse the body
338 		 */
339 		op->named.data = aml_op_start;
340 		op->named.length = 0;
341 	}
342 
343 	if (walk_state->opcode == AML_BANK_FIELD_OP) {
344 		/*
345 		 * Backup to beginning of bank_field declaration
346 		 * body_length is unknown until we parse the body
347 		 */
348 		op->named.data = aml_op_start;
349 		op->named.length = 0;
350 	}
351 
352 	parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state));
353 	acpi_ps_append_arg(parent_scope, op);
354 
355 	if (parent_scope) {
356 		op_info =
357 		    acpi_ps_get_opcode_info(parent_scope->common.aml_opcode);
358 		if (op_info->flags & AML_HAS_TARGET) {
359 			argument_count =
360 			    acpi_ps_get_argument_count(op_info->type);
361 			if (parent_scope->common.arg_list_length >
362 			    argument_count) {
363 				op->common.flags |= ACPI_PARSEOP_TARGET;
364 			}
365 		} else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) {
366 			op->common.flags |= ACPI_PARSEOP_TARGET;
367 		}
368 	}
369 
370 	if (walk_state->descending_callback != NULL) {
371 		/*
372 		 * Find the object. This will either insert the object into
373 		 * the namespace or simply look it up
374 		 */
375 		walk_state->op = *new_op = op;
376 
377 		status = walk_state->descending_callback(walk_state, &op);
378 		status = acpi_ps_next_parse_state(walk_state, op, status);
379 		if (status == AE_CTRL_PENDING) {
380 			status = AE_CTRL_PARSE_PENDING;
381 		}
382 	}
383 
384 	return_ACPI_STATUS(status);
385 }
386 
387 /*******************************************************************************
388  *
389  * FUNCTION:    acpi_ps_complete_op
390  *
391  * PARAMETERS:  walk_state          - Current state
392  *              op                  - Returned Op
393  *              status              - Parse status before complete Op
394  *
395  * RETURN:      Status
396  *
397  * DESCRIPTION: Complete Op
398  *
399  ******************************************************************************/
400 
401 acpi_status
acpi_ps_complete_op(struct acpi_walk_state * walk_state,union acpi_parse_object ** op,acpi_status status)402 acpi_ps_complete_op(struct acpi_walk_state *walk_state,
403 		    union acpi_parse_object **op, acpi_status status)
404 {
405 	acpi_status status2;
406 
407 	ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state);
408 
409 	/*
410 	 * Finished one argument of the containing scope
411 	 */
412 	walk_state->parser_state.scope->parse_scope.arg_count--;
413 
414 	/* Close this Op (will result in parse subtree deletion) */
415 
416 	status2 = acpi_ps_complete_this_op(walk_state, *op);
417 	if (ACPI_FAILURE(status2)) {
418 		return_ACPI_STATUS(status2);
419 	}
420 
421 	*op = NULL;
422 
423 	switch (status) {
424 	case AE_OK:
425 
426 		break;
427 
428 	case AE_CTRL_TRANSFER:
429 
430 		/* We are about to transfer to a called method */
431 
432 		walk_state->prev_op = NULL;
433 		walk_state->prev_arg_types = walk_state->arg_types;
434 		return_ACPI_STATUS(status);
435 
436 	case AE_CTRL_END:
437 
438 		acpi_ps_pop_scope(&(walk_state->parser_state), op,
439 				  &walk_state->arg_types,
440 				  &walk_state->arg_count);
441 
442 		if (*op) {
443 			walk_state->op = *op;
444 			walk_state->op_info =
445 			    acpi_ps_get_opcode_info((*op)->common.aml_opcode);
446 			walk_state->opcode = (*op)->common.aml_opcode;
447 
448 			status = walk_state->ascending_callback(walk_state);
449 			status =
450 			    acpi_ps_next_parse_state(walk_state, *op, status);
451 
452 			status2 = acpi_ps_complete_this_op(walk_state, *op);
453 			if (ACPI_FAILURE(status2)) {
454 				return_ACPI_STATUS(status2);
455 			}
456 		}
457 
458 		status = AE_OK;
459 		break;
460 
461 	case AE_CTRL_BREAK:
462 	case AE_CTRL_CONTINUE:
463 
464 		/* Pop off scopes until we find the While */
465 
466 		while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) {
467 			acpi_ps_pop_scope(&(walk_state->parser_state), op,
468 					  &walk_state->arg_types,
469 					  &walk_state->arg_count);
470 		}
471 
472 		/* Close this iteration of the While loop */
473 
474 		walk_state->op = *op;
475 		walk_state->op_info =
476 		    acpi_ps_get_opcode_info((*op)->common.aml_opcode);
477 		walk_state->opcode = (*op)->common.aml_opcode;
478 
479 		status = walk_state->ascending_callback(walk_state);
480 		status = acpi_ps_next_parse_state(walk_state, *op, status);
481 
482 		status2 = acpi_ps_complete_this_op(walk_state, *op);
483 		if (ACPI_FAILURE(status2)) {
484 			return_ACPI_STATUS(status2);
485 		}
486 
487 		status = AE_OK;
488 		break;
489 
490 	case AE_CTRL_TERMINATE:
491 
492 		/* Clean up */
493 		do {
494 			if (*op) {
495 				status2 =
496 				    acpi_ps_complete_this_op(walk_state, *op);
497 				if (ACPI_FAILURE(status2)) {
498 					return_ACPI_STATUS(status2);
499 				}
500 
501 				acpi_ut_delete_generic_state
502 				    (acpi_ut_pop_generic_state
503 				     (&walk_state->control_state));
504 			}
505 
506 			acpi_ps_pop_scope(&(walk_state->parser_state), op,
507 					  &walk_state->arg_types,
508 					  &walk_state->arg_count);
509 
510 		} while (*op);
511 
512 		return_ACPI_STATUS(AE_OK);
513 
514 	default:		/* All other non-AE_OK status */
515 
516 		do {
517 			if (*op) {
518 				status2 =
519 				    acpi_ps_complete_this_op(walk_state, *op);
520 				if (ACPI_FAILURE(status2)) {
521 					return_ACPI_STATUS(status2);
522 				}
523 			}
524 
525 			acpi_ps_pop_scope(&(walk_state->parser_state), op,
526 					  &walk_state->arg_types,
527 					  &walk_state->arg_count);
528 
529 		} while (*op);
530 
531 #if 0
532 		/*
533 		 * TBD: Cleanup parse ops on error
534 		 */
535 		if (*op == NULL) {
536 			acpi_ps_pop_scope(parser_state, op,
537 					  &walk_state->arg_types,
538 					  &walk_state->arg_count);
539 		}
540 #endif
541 		walk_state->prev_op = NULL;
542 		walk_state->prev_arg_types = walk_state->arg_types;
543 		return_ACPI_STATUS(status);
544 	}
545 
546 	/* This scope complete? */
547 
548 	if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) {
549 		acpi_ps_pop_scope(&(walk_state->parser_state), op,
550 				  &walk_state->arg_types,
551 				  &walk_state->arg_count);
552 		ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op));
553 	} else {
554 		*op = NULL;
555 	}
556 
557 	return_ACPI_STATUS(AE_OK);
558 }
559 
560 /*******************************************************************************
561  *
562  * FUNCTION:    acpi_ps_complete_final_op
563  *
564  * PARAMETERS:  walk_state          - Current state
565  *              op                  - Current Op
566  *              status              - Current parse status before complete last
567  *                                    Op
568  *
569  * RETURN:      Status
570  *
571  * DESCRIPTION: Complete last Op.
572  *
573  ******************************************************************************/
574 
575 acpi_status
acpi_ps_complete_final_op(struct acpi_walk_state * walk_state,union acpi_parse_object * op,acpi_status status)576 acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
577 			  union acpi_parse_object *op, acpi_status status)
578 {
579 	acpi_status status2;
580 
581 	ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state);
582 
583 	/*
584 	 * Complete the last Op (if not completed), and clear the scope stack.
585 	 * It is easily possible to end an AML "package" with an unbounded number
586 	 * of open scopes (such as when several ASL blocks are closed with
587 	 * sequential closing braces). We want to terminate each one cleanly.
588 	 */
589 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n",
590 			  op));
591 	do {
592 		if (op) {
593 			if (walk_state->ascending_callback != NULL) {
594 				walk_state->op = op;
595 				walk_state->op_info =
596 				    acpi_ps_get_opcode_info(op->common.
597 							    aml_opcode);
598 				walk_state->opcode = op->common.aml_opcode;
599 
600 				status =
601 				    walk_state->ascending_callback(walk_state);
602 				status =
603 				    acpi_ps_next_parse_state(walk_state, op,
604 							     status);
605 				if (status == AE_CTRL_PENDING) {
606 					status =
607 					    acpi_ps_complete_op(walk_state, &op,
608 								AE_OK);
609 					if (ACPI_FAILURE(status)) {
610 						return_ACPI_STATUS(status);
611 					}
612 				}
613 
614 				if (status == AE_CTRL_TERMINATE) {
615 					status = AE_OK;
616 
617 					/* Clean up */
618 					do {
619 						if (op) {
620 							status2 =
621 							    acpi_ps_complete_this_op
622 							    (walk_state, op);
623 							if (ACPI_FAILURE
624 							    (status2)) {
625 								return_ACPI_STATUS
626 								    (status2);
627 							}
628 						}
629 
630 						acpi_ps_pop_scope(&
631 								  (walk_state->
632 								   parser_state),
633 								  &op,
634 								  &walk_state->
635 								  arg_types,
636 								  &walk_state->
637 								  arg_count);
638 
639 					} while (op);
640 
641 					return_ACPI_STATUS(status);
642 				}
643 
644 				else if (ACPI_FAILURE(status)) {
645 
646 					/* First error is most important */
647 
648 					(void)
649 					    acpi_ps_complete_this_op(walk_state,
650 								     op);
651 					return_ACPI_STATUS(status);
652 				}
653 			}
654 
655 			status2 = acpi_ps_complete_this_op(walk_state, op);
656 			if (ACPI_FAILURE(status2)) {
657 				return_ACPI_STATUS(status2);
658 			}
659 		}
660 
661 		acpi_ps_pop_scope(&(walk_state->parser_state), &op,
662 				  &walk_state->arg_types,
663 				  &walk_state->arg_count);
664 
665 	} while (op);
666 
667 	return_ACPI_STATUS(status);
668 }
669