psparse.c

来自「讲述linux的初始化过程」· C语言 代码 · 共 1,234 行 · 第 1/2 页

C
1,234
字号
				}				/* We know that this arg is a name, move to next arg */				INCREMENT_ARG_LIST (arg_types);				if (walk_state->descending_callback != NULL) {					/*					 * Find the object.  This will either insert the object into					 * the namespace or simply look it up					 */					status = walk_state->descending_callback (opcode, NULL, walk_state, &op);					if (op == NULL) {						continue;					}					status = acpi_ps_next_parse_state (walk_state, op, status);					if (status == AE_CTRL_PENDING) {						status = AE_OK;						goto close_this_op;					}					if (ACPI_FAILURE (status)) {						goto close_this_op;					}				}				acpi_ps_append_arg (op, pre_op.value.arg);				acpi_gbl_depth++;				if (op->opcode == AML_REGION_OP) {					deferred_op = acpi_ps_to_extended_op (op);					if (deferred_op) {						/*						 * Defer final parsing of an Operation_region body,						 * because we don't have enough info in the first pass						 * to parse it correctly (i.e., there may be method						 * calls within the Term_arg elements of the body.						 *						 * However, we must continue parsing because						 * the opregion is not a standalone package --						 * we don't know where the end is at this point.						 *						 * (Length is unknown until parse of the body complete)						 */						deferred_op->data   = aml_op_start;						deferred_op->length = 0;					}				}			}			else {				/* Not a named opcode, just allocate Op and append to parent */				op = acpi_ps_alloc_op (opcode);				if (!op) {					return (AE_NO_MEMORY);				}				if ((op->opcode == AML_CREATE_FIELD_OP) ||					(op->opcode == AML_BIT_FIELD_OP)    ||					(op->opcode == AML_BYTE_FIELD_OP)   ||					(op->opcode == AML_WORD_FIELD_OP)   ||					(op->opcode == AML_DWORD_FIELD_OP))				 {					/*					 * Backup to beginning of Create_xXXfield declaration					 * Body_length is unknown until we parse the body					 */					deferred_op = (ACPI_PARSE2_OBJECT *) op;					deferred_op->data   = aml_op_start;					deferred_op->length = 0;				}				acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);				if ((walk_state->descending_callback != NULL)) {					/*					 * Find the object.  This will either insert the object into					 * the namespace or simply look it up					 */					status = walk_state->descending_callback (opcode, op, walk_state, &op);					status = acpi_ps_next_parse_state (walk_state, op, status);					if (status == AE_CTRL_PENDING) {						status = AE_OK;						goto close_this_op;					}					if (ACPI_FAILURE (status)) {						goto close_this_op;					}				}			}			op->aml_offset = aml_offset;		}		/* Start Arg_count at zero because we don't know if there are any args yet */		arg_count = 0;		if (arg_types)  /* Are there any arguments that must be processed? */ {			/* get arguments */			switch (op->opcode)			{			case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */			case AML_WORD_OP:       /* AML_WORDDATA_ARG */			case AML_DWORD_OP:      /* AML_DWORDATA_ARG */			case AML_STRING_OP:     /* AML_ASCIICHARLIST_ARG */				/* fill in constant or string argument directly */				acpi_ps_get_next_simple_arg (parser_state,						 GET_CURRENT_ARG_TYPE (arg_types), op);				break;			case AML_NAMEPATH_OP:   /* AML_NAMESTRING_ARG */				acpi_ps_get_next_namepath (parser_state, op, &arg_count, 1);				arg_types = 0;				break;			default:				/* Op is not a constant or string, append each argument */				while (GET_CURRENT_ARG_TYPE (arg_types) && !arg_count) {					aml_offset = parser_state->aml - parser_state->aml_start;					arg = acpi_ps_get_next_arg (parser_state,							 GET_CURRENT_ARG_TYPE (arg_types),							 &arg_count);					if (arg) {						arg->aml_offset = aml_offset;						acpi_ps_append_arg (op, arg);					}					INCREMENT_ARG_LIST (arg_types);				}				/* For a method, save the length and address of the body */				if (op->opcode == AML_METHOD_OP) {					deferred_op = acpi_ps_to_extended_op (op);					if (deferred_op) {						/*						 * Skip parsing of control method or opregion body,						 * because we don't have enough info in the first pass						 * to parse them correctly.						 */						deferred_op->data   = parser_state->aml;						deferred_op->length = parser_state->pkg_end -								  parser_state->aml;						/*						 * Skip body of method.  For Op_regions, we must continue						 * parsing because the opregion is not a standalone						 * package (We don't know where the end is).						 */						parser_state->aml   = parser_state->pkg_end;						arg_count           = 0;					}				}				break;			}		}		/*		 * Zero Arg_count means that all arguments for this op have been processed		 */		if (!arg_count) {			/* completed Op, prepare for next */			if (acpi_ps_is_named_op (op->opcode)) {				if (acpi_gbl_depth) {					acpi_gbl_depth--;				}				if (op->opcode == AML_REGION_OP) {					deferred_op = acpi_ps_to_extended_op (op);					if (deferred_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.						 */						deferred_op->length = parser_state->aml -								 deferred_op->data;					}				}			}			if ((op->opcode == AML_CREATE_FIELD_OP) ||				(op->opcode == AML_BIT_FIELD_OP)    ||				(op->opcode == AML_BYTE_FIELD_OP)   ||				(op->opcode == AML_WORD_FIELD_OP)   ||				(op->opcode == AML_DWORD_FIELD_OP)  ||				(op->opcode == AML_QWORD_FIELD_OP))			{				/*				 * Backup to beginning of Create_xXXfield declaration (1 for				 * Opcode)				 *				 * Body_length is unknown until we parse the body				 */				deferred_op = (ACPI_PARSE2_OBJECT *) op;				deferred_op->length = parser_state->aml - deferred_op->data;			}			/* This op complete, notify the dispatcher */			if (walk_state->ascending_callback != NULL) {				status = walk_state->ascending_callback (walk_state, op);				status = acpi_ps_next_parse_state (walk_state, op, status);				if (status == AE_CTRL_PENDING) {					status = AE_OK;					goto close_this_op;				}			}close_this_op:			/*			 * Finished one argument of the containing scope			 */			parser_state->scope->parse_scope.arg_count--;			/* Close this Op (may result in parse subtree deletion) */			if (acpi_ps_complete_this_op (walk_state, op)) {				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 = op;				walk_state->prev_arg_types = arg_types;				return (status);				break;			case AE_CTRL_END:				acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);				status = walk_state->ascending_callback (walk_state, op);				status = acpi_ps_next_parse_state (walk_state, op, status);				acpi_ps_complete_this_op (walk_state, op);				op = NULL;				status = AE_OK;				break;			case AE_CTRL_TERMINATE:				status = AE_OK;				/* Clean up */				do				{					if (op) {						acpi_ps_complete_this_op (walk_state, op);					}					acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);				} while (op);				return (status);				break;			default:  /* All other non-AE_OK status */				if (op == NULL) {					acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);				}				walk_state->prev_op = op;				walk_state->prev_arg_types = arg_types;				/*				 * TEMP:				 */				return (status);				break;			}			/* This scope complete? */			if (acpi_ps_has_completed_scope (parser_state)) {				acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);			}			else {				op = NULL;			}		}		/* Arg_count is non-zero */		else {			/* complex argument, push Op and prepare for argument */			acpi_ps_push_scope (parser_state, op, arg_types, arg_count);			op = NULL;		}	} /* while Parser_state->Aml */	/*	 * 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 AML blocks are closed with	 * sequential closing braces).  We want to terminate each one cleanly.	 */	do	{		if (op) {			if (walk_state->ascending_callback != NULL) {				status = walk_state->ascending_callback (walk_state, op);				status = acpi_ps_next_parse_state (walk_state, op, status);				if (status == AE_CTRL_PENDING) {					status = AE_OK;					goto close_this_op;				}				if (status == AE_CTRL_TERMINATE) {					status = AE_OK;					/* Clean up */					do					{						if (op) {							acpi_ps_complete_this_op (walk_state, op);						}						acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);					} while (op);					return (status);				}				else if (ACPI_FAILURE (status)) {					acpi_ps_complete_this_op (walk_state, op);					return (status);				}			}			acpi_ps_complete_this_op (walk_state, op);		}		acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);	} while (op);	return (status);}/******************************************************************************* * * FUNCTION:    Acpi_ps_parse_aml * * PARAMETERS:  Start_scope     - The starting point of the parse.  Becomes the *                                root of the parsed op tree. *              Aml             - Pointer to the raw AML code to parse *              Aml_size        - Length of the AML to parse * * RETURN:      Status * * DESCRIPTION: Parse raw AML and return a tree of ops * ******************************************************************************/ACPI_STATUSacpi_ps_parse_aml (	ACPI_PARSE_OBJECT       *start_scope,	u8                      *aml,	u32                     aml_size,	u32                     parse_flags,	ACPI_NAMESPACE_NODE     *method_node,	ACPI_OPERAND_OBJECT     **params,	ACPI_OPERAND_OBJECT     **caller_return_desc,	ACPI_PARSE_DOWNWARDS    descending_callback,	ACPI_PARSE_UPWARDS      ascending_callback){	ACPI_STATUS             status;	ACPI_PARSE_STATE        *parser_state;	ACPI_WALK_STATE         *walk_state;	ACPI_WALK_LIST          walk_list;	ACPI_NAMESPACE_NODE     *node = NULL;	ACPI_WALK_LIST          *prev_walk_list = acpi_gbl_current_walk_list;	ACPI_OPERAND_OBJECT     *return_desc;	ACPI_OPERAND_OBJECT     *mth_desc = NULL;	/* Create and initialize a new parser state */	parser_state = acpi_ps_create_state (aml, aml_size);	if (!parser_state) {		return (AE_NO_MEMORY);	}	acpi_ps_init_scope (parser_state, start_scope);	if (method_node) {		mth_desc = acpi_ns_get_attached_object (method_node);	}	/* Create and initialize a new walk list */	walk_list.walk_state = NULL;	walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, parser_state->start_op, mth_desc, &walk_list);	if (!walk_state) {		status = AE_NO_MEMORY;		goto cleanup;	}	walk_state->method_node         = method_node;	walk_state->parser_state        = parser_state;	walk_state->parse_flags         = parse_flags;	walk_state->descending_callback = descending_callback;	walk_state->ascending_callback  = ascending_callback;	/* TBD: [Restructure] TEMP until we pass Walk_state to the interpreter	 */	acpi_gbl_current_walk_list = &walk_list;	if (method_node) {		parser_state->start_node = method_node;		walk_state->walk_type   = WALK_METHOD;		/* Push start scope on scope stack and make it current  */		status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state);		if (ACPI_FAILURE (status)) {			return (status);		}		/* Init arguments if this is a control method */		/* TBD: [Restructure] add walkstate as a param */		acpi_ds_method_data_init_args (params, MTH_NUM_ARGS, walk_state);	}	else {		/* Setup the current scope */		node = parser_state->start_op->node;		parser_state->start_node = node;		if (node) {			/* Push start scope on scope stack and make it current  */			status = acpi_ds_scope_stack_push (node, node->type,					   walk_state);			if (ACPI_FAILURE (status)) {				goto cleanup;			}		}	}	status = AE_OK;	/*	 * Execute the walk loop as long as there is a valid Walk State.  This	 * handles nested control method invocations without recursion.	 */	while (walk_state) {		if (ACPI_SUCCESS (status)) {			status = acpi_ps_parse_loop (walk_state);		}		if (status == AE_CTRL_TRANSFER) {			/*			 * A method call was detected.			 * Transfer control to the called control method			 */			status = acpi_ds_call_control_method (&walk_list, walk_state, NULL);			/*			 * If the transfer to the new method method call worked, a new walk			 * state was created -- get it			 */			walk_state = acpi_ds_get_current_walk_state (&walk_list);			continue;		}		else if (status == AE_CTRL_TERMINATE) {			status = AE_OK;		}		/* We are done with this walk, move on to the parent if any */		walk_state = acpi_ds_pop_walk_state (&walk_list);		/* Extract return value before we delete Walk_state */		return_desc = walk_state->return_desc;		/* Reset the current scope to the beginning of scope stack */		acpi_ds_scope_stack_clear (walk_state);		/*		 * If we just returned from the execution of a control method,		 * there's lots of cleanup to do		 */		if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) {			acpi_ds_terminate_control_method (walk_state);		}		 /* Delete this walk state and all linked control states */		acpi_ps_cleanup_scope (walk_state->parser_state);		acpi_cm_free (walk_state->parser_state);		acpi_ds_delete_walk_state (walk_state);	   /* Check if we have restarted a preempted walk */		walk_state = acpi_ds_get_current_walk_state (&walk_list);		if (walk_state &&			ACPI_SUCCESS (status))		{			/* There is another walk state, restart it */			/*			 * If the method returned value is not used by the parent,			 * The object is deleted			 */			acpi_ds_restart_control_method (walk_state, return_desc);			walk_state->walk_type |= WALK_METHOD_RESTART;		}		/*		 * Just completed a 1st-level method, save the final internal return		 * value (if any)		 */		else if (caller_return_desc) {			*caller_return_desc = return_desc; /* NULL if no return value */		}		else if (return_desc) {			/* Caller doesn't want it, must delete it */			acpi_cm_remove_reference (return_desc);		}	}	/* Normal exit */	acpi_gbl_current_walk_list = prev_walk_list;	return (status);cleanup:	/* Cleanup */	acpi_ds_delete_walk_state (walk_state);	acpi_ps_cleanup_scope (parser_state);	acpi_cm_free (parser_state);	acpi_gbl_current_walk_list = prev_walk_list;	return (status);}

⌨️ 快捷键说明

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