psloop.c

来自「linux 内核源代码」· C语言 代码 · 共 1,057 行 · 第 1/2 页

C
1,057
字号
 *              Status              - Parse status before complete Op * * RETURN:      Status * * DESCRIPTION: Complete Op * ******************************************************************************/static acpi_statusacpi_ps_complete_op(struct acpi_walk_state *walk_state,		    union acpi_parse_object **op, acpi_status status){	acpi_status status2;	ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state);	/*	 * Finished one argument of the containing scope	 */	walk_state->parser_state.scope->parse_scope.arg_count--;	/* Close this Op (will result in parse subtree deletion) */	status2 = acpi_ps_complete_this_op(walk_state, *op);	if (ACPI_FAILURE(status2)) {		return_ACPI_STATUS(status2);	}	*op = NULL;	switch (status) {	case AE_OK:		break;	case AE_CTRL_TRANSFER:		/* We are about to transfer to a called method */		walk_state->prev_op = NULL;		walk_state->prev_arg_types = walk_state->arg_types;		return_ACPI_STATUS(status);	case AE_CTRL_END:		acpi_ps_pop_scope(&(walk_state->parser_state), op,				  &walk_state->arg_types,				  &walk_state->arg_count);		if (*op) {			walk_state->op = *op;			walk_state->op_info =			    acpi_ps_get_opcode_info((*op)->common.aml_opcode);			walk_state->opcode = (*op)->common.aml_opcode;			status = walk_state->ascending_callback(walk_state);			status =			    acpi_ps_next_parse_state(walk_state, *op, status);			status2 = acpi_ps_complete_this_op(walk_state, *op);			if (ACPI_FAILURE(status2)) {				return_ACPI_STATUS(status2);			}		}		status = AE_OK;		break;	case AE_CTRL_BREAK:	case AE_CTRL_CONTINUE:		/* Pop off scopes until we find the While */		while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) {			acpi_ps_pop_scope(&(walk_state->parser_state), op,					  &walk_state->arg_types,					  &walk_state->arg_count);			if ((*op)->common.aml_opcode != AML_WHILE_OP) {				status2 = acpi_ds_result_stack_pop(walk_state);				if (ACPI_FAILURE(status2)) {					return_ACPI_STATUS(status2);				}			}		}		/* Close this iteration of the While loop */		walk_state->op = *op;		walk_state->op_info =		    acpi_ps_get_opcode_info((*op)->common.aml_opcode);		walk_state->opcode = (*op)->common.aml_opcode;		status = walk_state->ascending_callback(walk_state);		status = acpi_ps_next_parse_state(walk_state, *op, status);		status2 = acpi_ps_complete_this_op(walk_state, *op);		if (ACPI_FAILURE(status2)) {			return_ACPI_STATUS(status2);		}		status = AE_OK;		break;	case AE_CTRL_TERMINATE:		/* Clean up */		do {			if (*op) {				status2 =				    acpi_ps_complete_this_op(walk_state, *op);				if (ACPI_FAILURE(status2)) {					return_ACPI_STATUS(status2);				}				status2 = acpi_ds_result_stack_pop(walk_state);				if (ACPI_FAILURE(status2)) {					return_ACPI_STATUS(status2);				}				acpi_ut_delete_generic_state				    (acpi_ut_pop_generic_state				     (&walk_state->control_state));			}			acpi_ps_pop_scope(&(walk_state->parser_state), op,					  &walk_state->arg_types,					  &walk_state->arg_count);		} while (*op);		return_ACPI_STATUS(AE_OK);	default:		/* All other non-AE_OK status */		do {			if (*op) {				status2 =				    acpi_ps_complete_this_op(walk_state, *op);				if (ACPI_FAILURE(status2)) {					return_ACPI_STATUS(status2);				}			}			acpi_ps_pop_scope(&(walk_state->parser_state), op,					  &walk_state->arg_types,					  &walk_state->arg_count);		} while (*op);#if 0		/*		 * TBD: Cleanup parse ops on error		 */		if (*op == NULL) {			acpi_ps_pop_scope(parser_state, op,					  &walk_state->arg_types,					  &walk_state->arg_count);		}#endif		walk_state->prev_op = NULL;		walk_state->prev_arg_types = walk_state->arg_types;		return_ACPI_STATUS(status);	}	/* This scope complete? */	if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) {		acpi_ps_pop_scope(&(walk_state->parser_state), op,				  &walk_state->arg_types,				  &walk_state->arg_count);		ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op));	} else {		*op = NULL;	}	return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION:    acpi_ps_complete_final_op * * PARAMETERS:  walk_state          - Current state *              Op                  - Current Op *              Status              - Current parse status before complete last *                                    Op * * RETURN:      Status * * DESCRIPTION: Complete last Op. * ******************************************************************************/static acpi_statusacpi_ps_complete_final_op(struct acpi_walk_state *walk_state,			  union acpi_parse_object *op, acpi_status status){	acpi_status status2;	ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state);	/*	 * Complete the last Op (if not completed), and clear the scope stack.	 * It is easily possible to end an AML "package" with an unbounded number	 * of open scopes (such as when several ASL blocks are closed with	 * sequential closing braces). We want to terminate each one cleanly.	 */	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n",			  op));	do {		if (op) {			if (walk_state->ascending_callback != NULL) {				walk_state->op = op;				walk_state->op_info =				    acpi_ps_get_opcode_info(op->common.							    aml_opcode);				walk_state->opcode = op->common.aml_opcode;				status =				    walk_state->ascending_callback(walk_state);				status =				    acpi_ps_next_parse_state(walk_state, op,							     status);				if (status == AE_CTRL_PENDING) {					status =					    acpi_ps_complete_op(walk_state, &op,								AE_OK);					if (ACPI_FAILURE(status)) {						return_ACPI_STATUS(status);					}				}				if (status == AE_CTRL_TERMINATE) {					status = AE_OK;					/* Clean up */					do {						if (op) {							status2 =							    acpi_ps_complete_this_op							    (walk_state, op);							if (ACPI_FAILURE							    (status2)) {								return_ACPI_STATUS								    (status2);							}						}						acpi_ps_pop_scope(&								  (walk_state->								   parser_state),								  &op,								  &walk_state->								  arg_types,								  &walk_state->								  arg_count);					} while (op);					return_ACPI_STATUS(status);				}				else if (ACPI_FAILURE(status)) {					/* First error is most important */					(void)					    acpi_ps_complete_this_op(walk_state,								     op);					return_ACPI_STATUS(status);				}			}			status2 = acpi_ps_complete_this_op(walk_state, op);			if (ACPI_FAILURE(status2)) {				return_ACPI_STATUS(status2);			}		}		acpi_ps_pop_scope(&(walk_state->parser_state), &op,				  &walk_state->arg_types,				  &walk_state->arg_count);	} while (op);	return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION:    acpi_ps_parse_loop * * PARAMETERS:  walk_state          - Current state * * RETURN:      Status * * DESCRIPTION: Parse AML (pointed to by the current parser state) and return *              a tree of ops. * ******************************************************************************/acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state){	acpi_status status = AE_OK;	union acpi_parse_object *op = NULL;	/* current op */	struct acpi_parse_state *parser_state;	u8 *aml_op_start = NULL;	ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);	if (walk_state->descending_callback == NULL) {		return_ACPI_STATUS(AE_BAD_PARAMETER);	}	parser_state = &walk_state->parser_state;	walk_state->arg_types = 0;#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))	if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {		/* We are restarting a preempted control method */		if (acpi_ps_has_completed_scope(parser_state)) {			/*			 * We must check if a predicate to an IF or WHILE statement			 * was just completed			 */			if ((parser_state->scope->parse_scope.op) &&			    ((parser_state->scope->parse_scope.op->common.			      aml_opcode == AML_IF_OP)			     || (parser_state->scope->parse_scope.op->common.				 aml_opcode == AML_WHILE_OP))			    && (walk_state->control_state)			    && (walk_state->control_state->common.state ==				ACPI_CONTROL_PREDICATE_EXECUTING)) {				/*				 * A predicate was just completed, get the value of the				 * predicate and branch based on that value				 */				walk_state->op = NULL;				status =				    acpi_ds_get_predicate_value(walk_state,								ACPI_TO_POINTER								(TRUE));				if (ACPI_FAILURE(status)				    && ((status & AE_CODE_MASK) !=					AE_CODE_CONTROL)) {					if (status == AE_AML_NO_RETURN_VALUE) {						ACPI_EXCEPTION((AE_INFO, status,								"Invoked method did not return a value"));					}					ACPI_EXCEPTION((AE_INFO, status,							"GetPredicate Failed"));					return_ACPI_STATUS(status);				}				status =				    acpi_ps_next_parse_state(walk_state, op,							     status);			}			acpi_ps_pop_scope(parser_state, &op,					  &walk_state->arg_types,					  &walk_state->arg_count);			ACPI_DEBUG_PRINT((ACPI_DB_PARSE,					  "Popped scope, Op=%p\n", op));		} else if (walk_state->prev_op) {			/* We were in the middle of an op */			op = walk_state->prev_op;			walk_state->arg_types = walk_state->prev_arg_types;		}	}#endif	/* Iterative parsing loop, while there is more AML to process: */	while ((parser_state->aml < parser_state->aml_end) || (op)) {		aml_op_start = parser_state->aml;		if (!op) {			status =			    acpi_ps_create_op(walk_state, aml_op_start, &op);			if (ACPI_FAILURE(status)) {				if (status == AE_CTRL_PARSE_CONTINUE) {					continue;				}				if (status == AE_CTRL_PARSE_PENDING) {					status = AE_OK;				}				status =				    acpi_ps_complete_op(walk_state, &op,							status);				if (ACPI_FAILURE(status)) {					return_ACPI_STATUS(status);				}				continue;			}			op->common.aml_offset = walk_state->aml_offset;			if (walk_state->op_info) {				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,						  "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n",						  (u32) op->common.aml_opcode,						  walk_state->op_info->name, op,						  parser_state->aml,						  op->common.aml_offset));			}		}		/*		 * Start arg_count at zero because we don't know if there are		 * any args yet		 */		walk_state->arg_count = 0;		/* Are there any arguments that must be processed? */		if (walk_state->arg_types) {			/* Get arguments */			status =			    acpi_ps_get_arguments(walk_state, aml_op_start, op);			if (ACPI_FAILURE(status)) {				status =				    acpi_ps_complete_op(walk_state, &op,							status);				if (ACPI_FAILURE(status)) {					return_ACPI_STATUS(status);				}				continue;			}		}		/* Check for arguments that need to be processed */		if (walk_state->arg_count) {			/*			 * There are arguments (complex ones), push Op and			 * prepare for argument			 */			status = acpi_ps_push_scope(parser_state, op,						    walk_state->arg_types,						    walk_state->arg_count);			if (ACPI_FAILURE(status)) {				status =				    acpi_ps_complete_op(walk_state, &op,							status);				if (ACPI_FAILURE(status)) {					return_ACPI_STATUS(status);				}				continue;			}			op = NULL;			continue;		}		/*		 * All arguments have been processed -- Op is complete,		 * prepare for next		 */		walk_state->op_info =		    acpi_ps_get_opcode_info(op->common.aml_opcode);		if (walk_state->op_info->flags & AML_NAMED) {			if (acpi_gbl_depth) {				acpi_gbl_depth--;			}			if (op->common.aml_opcode == AML_REGION_OP) {				/*				 * Skip parsing of control method or opregion body,				 * because we don't have enough info in the first pass				 * to parse them correctly.				 *				 * Completed parsing an op_region declaration, we now				 * know the length.				 */				op->named.length =				    (u32) (parser_state->aml - op->named.data);			}		}		if (walk_state->op_info->flags & AML_CREATE) {			/*			 * Backup to beginning of create_xXXfield declaration (1 for			 * Opcode)			 *			 * body_length is unknown until we parse the body			 */			op->named.length =			    (u32) (parser_state->aml - op->named.data);		}		/* This op complete, notify the dispatcher */		if (walk_state->ascending_callback != NULL) {			walk_state->op = op;			walk_state->opcode = op->common.aml_opcode;			status = walk_state->ascending_callback(walk_state);			status =			    acpi_ps_next_parse_state(walk_state, op, status);			if (status == AE_CTRL_PENDING) {				status = AE_OK;			}		}		status = acpi_ps_complete_op(walk_state, &op, status);		if (ACPI_FAILURE(status)) {			return_ACPI_STATUS(status);		}	}			/* while parser_state->Aml */	status = acpi_ps_complete_final_op(walk_state, op, status);	return_ACPI_STATUS(status);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?