⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psparse.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************** * * Module Name: psparse - Parser top level AML parse routines *              $Revision: 104 $ * *****************************************************************************//* *  Copyright (C) 2000, 2001 R. Byron Moore * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *//* * Parse the AML and build an operation tree as most interpreters, * like Perl, do.  Parsing is done by hand rather than with a YACC * generated parser to tightly constrain stack and dynamic memory * usage.  At the same time, parsing is kept flexible and the code * fairly compact by parsing based on a list of AML opcode * templates in Aml_op_info[] */#include "acpi.h"#include "acparser.h"#include "acdispat.h"#include "amlcode.h"#include "acnamesp.h"#include "acdebug.h"#include "acinterp.h"#define _COMPONENT          ACPI_PARSER	 MODULE_NAME         ("psparse")u32                         acpi_gbl_depth = 0;extern u32                  acpi_gbl_scope_depth;/******************************************************************************* * * FUNCTION:    Acpi_ps_get_opcode_size * * PARAMETERS:  Opcode          - An AML opcode * * RETURN:      Size of the opcode, in bytes (1 or 2) * * DESCRIPTION: Get the size of the current opcode. * ******************************************************************************/static u32acpi_ps_get_opcode_size (	u32                     opcode){	/* Extended (2-byte) opcode if > 255 */	if (opcode > 0x00FF) {		return (2);	}	/* Otherwise, just a single byte opcode */	return (1);}/******************************************************************************* * * FUNCTION:    Acpi_ps_peek_opcode * * PARAMETERS:  Parser_state        - A parser state object * * RETURN:      Status * * DESCRIPTION: Get next AML opcode (without incrementing AML pointer) * ******************************************************************************/u16acpi_ps_peek_opcode (	acpi_parse_state        *parser_state){	u8                      *aml;	u16                     opcode;	aml = parser_state->aml;	opcode = (u16) GET8 (aml);	aml++;	/*	 * Original code special cased LNOTEQUAL, LLESSEQUAL, LGREATEREQUAL.	 * These opcodes are no longer recognized. Instead, they are broken into	 * two opcodes.	 *	 *	 *    if (Opcode == AML_EXTOP	 *       || (Opcode == AML_LNOT	 *          && (GET8 (Aml) == AML_LEQUAL	 *               || GET8 (Aml) == AML_LGREATER	 *               || GET8 (Aml) == AML_LLESS)))	 *	 *     extended Opcode, !=, <=, or >=	 */	if (opcode == AML_EXTOP) {		/* Extended opcode */		opcode = (u16) ((opcode << 8) | GET8 (aml));	}	return (opcode);}/******************************************************************************* * * FUNCTION:    Acpi_ps_find_object * * PARAMETERS:  Opcode          - Current opcode *              Parser_state    - Current state *              Walk_state      - Current state *              *Op             - Where found/new op is returned * * RETURN:      Status * * DESCRIPTION: Find a named object.  Two versions - one to search the parse *              tree (for parser-only applications such as acpidump), another *              to search the ACPI internal namespace (the parse tree may no *              longer exist) * ******************************************************************************/#ifdef PARSER_ONLYacpi_statusacpi_ps_find_object (	acpi_walk_state         *walk_state,	acpi_parse_object       **out_op){	NATIVE_CHAR             *path;	/* We are only interested in opcodes that have an associated name */	if (!(walk_state->op_info->flags & AML_NAMED)) {		*out_op = walk_state->op;		return (AE_OK);	}	/* Find the name in the parse tree */	path = acpi_ps_get_next_namestring (&walk_state->parser_state);	*out_op = acpi_ps_find (acpi_ps_get_parent_scope (&walk_state->parser_state),			  path, walk_state->opcode, 1);	if (!(*out_op)) {		return (AE_NOT_FOUND);	}	return (AE_OK);}#endif/******************************************************************************* * * FUNCTION:    Acpi_ps_complete_this_op * * PARAMETERS:  Walk_state      - Current State *              Op              - Op to complete * * RETURN:      TRUE if Op and subtree was deleted * * DESCRIPTION: Perform any cleanup at the completion of an Op. * ******************************************************************************/static u8acpi_ps_complete_this_op (	acpi_walk_state         *walk_state,	acpi_parse_object       *op){#ifndef PARSER_ONLY	acpi_parse_object       *prev;	acpi_parse_object       *next;	const acpi_opcode_info  *parent_info;	acpi_parse_object       *replacement_op = NULL;	FUNCTION_TRACE_PTR ("Ps_complete_this_op", op);	/* Delete this op and the subtree below it if asked to */	if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) &&		(walk_state->op_info->class != AML_CLASS_ARGUMENT)) {		/* Make sure that we only delete this subtree */		if (op->parent) {			/*			 * Check if we need to replace the operator and its subtree			 * with a return value op (placeholder op)			 */			parent_info = acpi_ps_get_opcode_info (op->parent->opcode);			switch (parent_info->class) {			case AML_CLASS_CONTROL:        /* IF, ELSE, WHILE only */				break;			case AML_CLASS_NAMED_OBJECT:   /* Scope, method, etc. */			case AML_CLASS_CREATE:				/*				 * These opcodes contain Term_arg operands. The current				 * op must be replace by a placeholder return op				 */				if ((op->parent->opcode == AML_REGION_OP)               ||					(op->parent->opcode == AML_CREATE_FIELD_OP)         ||					(op->parent->opcode == AML_CREATE_BIT_FIELD_OP)     ||					(op->parent->opcode == AML_CREATE_BYTE_FIELD_OP)    ||					(op->parent->opcode == AML_CREATE_WORD_FIELD_OP)    ||					(op->parent->opcode == AML_CREATE_DWORD_FIELD_OP)   ||					(op->parent->opcode == AML_CREATE_QWORD_FIELD_OP)) {					replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);					if (!replacement_op) {						return_VALUE (FALSE);					}				}				break;			default:				replacement_op = acpi_ps_alloc_op (AML_INT_RETURN_VALUE_OP);				if (!replacement_op) {					return_VALUE (FALSE);				}			}			/* We must unlink this op from the parent tree */			prev = op->parent->value.arg;			if (prev == op) {				/* This op is the first in the list */				if (replacement_op) {					replacement_op->parent   = op->parent;					replacement_op->value.arg = NULL;					op->parent->value.arg    = replacement_op;					replacement_op->next     = op->next;				}				else {					op->parent->value.arg    = op->next;				}			}			/* Search the parent list */			else while (prev) {				/* Traverse all siblings in the parent's argument list */				next = prev->next;				if (next == op) {					if (replacement_op) {						replacement_op->parent = op->parent;						replacement_op->value.arg = NULL;						prev->next = replacement_op;						replacement_op->next = op->next;						next = NULL;					}					else {						prev->next = op->next;						next = NULL;					}				}				prev = next;			}		}		/* Now we can actually delete the subtree rooted at op */		acpi_ps_delete_parse_tree (op);		return_VALUE (TRUE);	}	return_VALUE (FALSE);#else	return (FALSE);#endif}/******************************************************************************* * * FUNCTION:    Acpi_ps_next_parse_state * * PARAMETERS:  Parser_state        - Current parser state object * * RETURN: * * DESCRIPTION: * ******************************************************************************/static acpi_statusacpi_ps_next_parse_state (	acpi_walk_state         *walk_state,	acpi_parse_object       *op,	acpi_status             callback_status){	acpi_parse_state        *parser_state = &walk_state->parser_state;	acpi_status             status = AE_CTRL_PENDING;	u8                      *start;	u32                     package_length;	FUNCTION_TRACE_PTR ("Ps_next_parse_state", op);	switch (callback_status) {	case AE_CTRL_TERMINATE:		/*		 * A control method was terminated via a RETURN statement.		 * The walk of this method is complete.		 */		parser_state->aml = parser_state->aml_end;		status = AE_CTRL_TERMINATE;		break;	case AE_CTRL_PENDING:		/*		 * Predicate of a WHILE was true and the loop just completed an		 * execution.  Go back to the start of the loop and reevaluate the		 * predicate.		 */		/* TBD: How to handle a break within a while. */		/* This code attempts it */		parser_state->aml = walk_state->aml_last_while;		break;	case AE_CTRL_TRUE:		/*		 * Predicate of an IF was true, and we are at the matching ELSE.		 * Just close out this package		 *		 * Note: Parser_state->Aml is modified by the package length procedure		 * TBD: [Investigate] perhaps it shouldn't, too much trouble		 */		start = parser_state->aml;		package_length = acpi_ps_get_next_package_length (parser_state);		parser_state->aml = start + package_length;		break;	case AE_CTRL_FALSE:		/*		 * Either an IF/WHILE Predicate was false or we encountered a BREAK		 * opcode.  In both cases, we do not execute the rest of the		 * package;  We simply close out the parent (finishing the walk of		 * this branch of the tree) and continue execution at the parent		 * level.		 */		parser_state->aml = parser_state->scope->parse_scope.pkg_end;		/* In the case of a BREAK, just force a predicate (if any) to FALSE */		walk_state->control_state->common.value = FALSE;		status = AE_CTRL_END;		break;	case AE_CTRL_TRANSFER:		/*		 * A method call (invocation) -- transfer control		 */		status = AE_CTRL_TRANSFER;		walk_state->prev_op = op;		walk_state->method_call_op = op;		walk_state->method_call_node = (op->value.arg)->node;		/* Will return value (if any) be used by the caller? */		walk_state->return_used = acpi_ds_is_result_used (op, walk_state);		break;	default:		status = callback_status;		if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) {			status = AE_OK;		}		break;	}	return_ACPI_STATUS (status);}/******************************************************************************* * * FUNCTION:    Acpi_ps_parse_loop * * PARAMETERS:  Parser_state        - Current parser state object * * RETURN:      Status * * DESCRIPTION: Parse AML (pointed to by the current parser state) and return *              a tree of ops. * ******************************************************************************/acpi_statusacpi_ps_parse_loop (	acpi_walk_state         *walk_state){	acpi_status             status = AE_OK;	acpi_parse_object       *op = NULL;     /* current op */	acpi_parse_object       *arg = NULL;	acpi_parse_object       pre_op;	acpi_parse_state        *parser_state;	u8                      *aml_op_start;	FUNCTION_TRACE_PTR ("Ps_parse_loop", walk_state);	parser_state = &walk_state->parser_state;	walk_state->arg_types = 0;#ifndef PARSER_ONLY	if (walk_state->walk_type & 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->opcode == AML_IF_OP) ||				(parser_state->scope->parse_scope.op->opcode == AML_WHILE_OP)) &&				(walk_state->control_state) &&				(walk_state->control_state->common.state ==					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, TRUE);				if (ACPI_FAILURE (status) &&					((status & AE_CODE_MASK) != AE_CODE_CONTROL)) {					if (status == AE_AML_NO_RETURN_VALUE) {						ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,							"Invoked method did not return a value, %s\n",							acpi_format_exception (status)));					}					ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Get_predicate Failed, %s\n",						acpi_format_exception (status)));					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)) {		if (!op) {			/* Get the next opcode from the AML stream */			aml_op_start = parser_state->aml;			walk_state->aml_offset = parser_state->aml - parser_state->aml_start;			walk_state->opcode    = acpi_ps_peek_opcode (parser_state);			/*			 * First cut to determine what we have found:			 * 1) A valid AML opcode			 * 2) A name string			 * 3) An unknown/invalid opcode			 */			walk_state->op_info = acpi_ps_get_opcode_info (walk_state->opcode);			switch (walk_state->op_info->class) {			case AML_CLASS_ASCII:			case AML_CLASS_PREFIX:				/*				 * Starts with a valid prefix or ASCII char, this is a name				 * string.  Convert the bare name string to a namepath.				 */				walk_state->opcode = AML_INT_NAMEPATH_OP;				walk_state->arg_types = ARGP_NAMESTRING;				break;			case AML_CLASS_UNKNOWN:				/* The opcode is unrecognized.  Just skip unknown opcodes */				ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,					"Found unknown opcode %X at AML offset %X, ignoring\n",					walk_state->opcode, walk_state->aml_offset));				DUMP_BUFFER (parser_state->aml, 128);				/* Assume one-byte bad opcode */				parser_state->aml++;				continue;			default:				/* Found opcode info, this is a normal opcode */				parser_state->aml += acpi_ps_get_opcode_size (walk_state->opcode);				walk_state->arg_types = walk_state->op_info->parse_args;				break;			}

⌨️ 快捷键说明

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