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

📄 psparse.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************
 *
 * Module Name: psparse - Parser top level AML parse routines
 *              $Revision: 1.1 $
 *
 *****************************************************************************/

/*
 *  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>

#define _COMPONENT          ACPI_PARSER
	 MODULE_NAME         ("psparse")


u32                         acpi_gbl_depth = 0;
extern u32                  acpi_gbl_scope_depth;


/*******************************************************************************
 *
 * FUNCTION:    Acpi_ps_peek_opcode
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get next AML opcode (without incrementing AML pointer)
 *
 ******************************************************************************/

static u32
acpi_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)
 *
 ******************************************************************************/

u16
acpi_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 (Acpi_aml) == AML_LEQUAL
	 *               || GET8 (Acpi_aml) == AML_LGREATER
	 *               || GET8 (Acpi_aml) == AML_LLESS)))
	 *
	 *     extended Opcode, !=, <=, or >=
	 */

	if (opcode == AML_EXTOP) {
		/* Extended opcode */

		opcode = (u16) ((opcode << 8) | GET8 (aml));
		aml++;
	}

	/* don't convert bare name to a namepath */

	return (opcode);
}


/*******************************************************************************
 *
 * FUNCTION:    Acpi_ps_create_state
 *
 * PARAMETERS:  Acpi_aml            - Acpi_aml code pointer
 *              Acpi_aml_size       - Length of AML code
 *
 * RETURN:      A new parser state object
 *
 * DESCRIPTION: Create and initialize a new parser state object
 *
 ******************************************************************************/

ACPI_PARSE_STATE *
acpi_ps_create_state (
	u8                      *aml,
	u32                     aml_size)
{
	ACPI_PARSE_STATE        *parser_state;


	parser_state = acpi_cm_callocate (sizeof (ACPI_PARSE_STATE));
	if (!parser_state) {
		return (NULL);
	}

	parser_state->aml      = aml;
	parser_state->aml_end  = aml + aml_size;
	parser_state->pkg_end  = parser_state->aml_end;
	parser_state->aml_start = aml;


	return (parser_state);
}


/*******************************************************************************
 *
 * 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_ONLY

ACPI_STATUS
acpi_ps_find_object (
	u16                     opcode,
	ACPI_PARSE_OBJECT       *op,
	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 (!acpi_ps_is_named_op (opcode)) {
		*out_op = 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, 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 u8
acpi_ps_complete_this_op (
	ACPI_WALK_STATE         *walk_state,
	ACPI_PARSE_OBJECT       *op)
{
#ifndef PARSER_ONLY
	ACPI_PARSE_OBJECT       *prev;
	ACPI_PARSE_OBJECT       *next;
	ACPI_OPCODE_INFO        *op_info;
	ACPI_OPCODE_INFO        *parent_info;
	u32                     opcode_class;
	ACPI_PARSE_OBJECT       *replacement_op = NULL;


	op_info     = acpi_ps_get_opcode_info (op->opcode);
	opcode_class = ACPI_GET_OP_CLASS (op_info);


	/* Delete this op and the subtree below it if asked to */

	if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) &&
		(opcode_class != OPTYPE_CONSTANT)       &&
		(opcode_class != OPTYPE_LITERAL)        &&
		(opcode_class != OPTYPE_LOCAL_VARIABLE) &&
		(opcode_class != OPTYPE_METHOD_ARGUMENT) &&
		(opcode_class != OPTYPE_DATA_TERM)      &&
		(op->opcode  != AML_NAMEPATH_OP)) {
		/* 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 (ACPI_GET_OP_CLASS (parent_info)) {
			case OPTYPE_CONTROL:        /* IF, ELSE, WHILE only */
				break;

			case OPTYPE_NAMED_OBJECT:   /* Scope, method, etc. */

				/*
				 * 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_BIT_FIELD_OP)    ||
					(op->parent->opcode == AML_BYTE_FIELD_OP)   ||
					(op->parent->opcode == AML_WORD_FIELD_OP)   ||
					(op->parent->opcode == AML_DWORD_FIELD_OP)  ||
					(op->parent->opcode == AML_QWORD_FIELD_OP)) {
					replacement_op = acpi_ps_alloc_op (AML_RETURN_VALUE_OP);
					if (!replacement_op) {
						return (FALSE);
					}
				}

				break;

			default:
				replacement_op = acpi_ps_alloc_op (AML_RETURN_VALUE_OP);
				if (!replacement_op) {
					return (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 (TRUE);
	}

	return (FALSE);

#else
	return (FALSE);
#endif
}


/*******************************************************************************
 *
 * FUNCTION:    Acpi_ps_next_parse_state
 *
 * PARAMETERS:  Parser_state        - Current parser state object
 *
 * RETURN:
 *
 * DESCRIPTION:
 *
 ******************************************************************************/

static ACPI_STATUS
acpi_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;


	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.
			 */
/*            Walk_state->Control_state->Common.State =
					CONTROL_PREDICATE_EXECUTING;*/

		/* TBD: How to handle a break within a while. */
		/* This code attempts it */

⌨️ 快捷键说明

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