示例#1
0
文件: dswload.c 项目: 274914765/C
acpi_status
acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
               union acpi_parse_object ** out_op)
{
    union acpi_parse_object *op;
    struct acpi_namespace_node *node;
    acpi_status status;
    acpi_object_type object_type;
    char *path;
    u32 flags;

    ACPI_FUNCTION_TRACE(ds_load1_begin_op);

    op = walk_state->op;
    ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
              walk_state));

    /* We are only interested in opcodes that have an associated name */

    if (op) {
        if (!(walk_state->op_info->flags & AML_NAMED)) {
            *out_op = op;
            return_ACPI_STATUS(AE_OK);
        }

        /* Check if this object has already been installed in the namespace */

        if (op->common.node) {
            *out_op = op;
            return_ACPI_STATUS(AE_OK);
        }
    }

    path = acpi_ps_get_next_namestring(&walk_state->parser_state);

    /* Map the raw opcode into an internal object type */

    object_type = walk_state->op_info->object_type;

    ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
              "State=%p Op=%p [%s]\n", walk_state, op,
              acpi_ut_get_type_name(object_type)));

    switch (walk_state->opcode) {
    case AML_SCOPE_OP:

        /*
         * The target name of the Scope() operator must exist at this point so
         * that we can actually open the scope to enter new names underneath it.
         * Allow search-to-root for single namesegs.
         */
        status =
            acpi_ns_lookup(walk_state->scope_info, path, object_type,
                   ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
                   walk_state, &(node));
#ifdef ACPI_ASL_COMPILER
        if (status == AE_NOT_FOUND) {
            /*
             * Table disassembly:
             * Target of Scope() not found. Generate an External for it, and
             * insert the name into the namespace.
             */
            acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0);
            status =
                acpi_ns_lookup(walk_state->scope_info, path,
                       object_type, ACPI_IMODE_LOAD_PASS1,
                       ACPI_NS_SEARCH_PARENT, walk_state,
                       &node);
        }
#endif
        if (ACPI_FAILURE(status)) {
            ACPI_ERROR_NAMESPACE(path, status);
            return_ACPI_STATUS(status);
        }

        /*
         * Check to make sure that the target is
         * one of the opcodes that actually opens a scope
         */
        switch (node->type) {
        case ACPI_TYPE_ANY:
        case ACPI_TYPE_LOCAL_SCOPE:    /* Scope  */
        case ACPI_TYPE_DEVICE:
        case ACPI_TYPE_POWER:
        case ACPI_TYPE_PROCESSOR:
        case ACPI_TYPE_THERMAL:

            /* These are acceptable types */
            break;

        case ACPI_TYPE_INTEGER:
        case ACPI_TYPE_STRING:
        case ACPI_TYPE_BUFFER:

            /*
             * These types we will allow, but we will change the type. This
             * enables some existing code of the form:
             *
             *  Name (DEB, 0)
             *  Scope (DEB) { ... }
             *
             * Note: silently change the type here. On the second pass, we will report
             * a warning
             */
            ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                      "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
                      path,
                      acpi_ut_get_type_name(node->type)));

            node->type = ACPI_TYPE_ANY;
            walk_state->scope_info->common.value = ACPI_TYPE_ANY;
            break;

        default:

            /* All other types are an error */

            ACPI_ERROR((AE_INFO,
                    "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)",
                    acpi_ut_get_type_name(node->type), path));

            return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
        }
        break;

    default:
        /*
         * For all other named opcodes, we will enter the name into
         * the namespace.
         *
         * Setup the search flags.
         * Since we are entering a name into the namespace, we do not want to
         * enable the search-to-root upsearch.
         *
         * There are only two conditions where it is acceptable that the name
         * already exists:
         *    1) the Scope() operator can reopen a scoping object that was
         *       previously defined (Scope, Method, Device, etc.)
         *    2) Whenever we are parsing a deferred opcode (op_region, Buffer,
         *       buffer_field, or Package), the name of the object is already
         *       in the namespace.
         */
        if (walk_state->deferred_node) {

            /* This name is already in the namespace, get the node */

            node = walk_state->deferred_node;
            status = AE_OK;
            break;
        }

        /*
         * If we are executing a method, do not create any namespace objects
         * during the load phase, only during execution.
         */
        if (walk_state->method_node) {
            node = NULL;
            status = AE_OK;
            break;
        }

        flags = ACPI_NS_NO_UPSEARCH;
        if ((walk_state->opcode != AML_SCOPE_OP) &&
            (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
            flags |= ACPI_NS_ERROR_IF_FOUND;
            ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                      "[%s] Cannot already exist\n",
                      acpi_ut_get_type_name(object_type)));
        } else {
            ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                      "[%s] Both Find or Create allowed\n",
                      acpi_ut_get_type_name(object_type)));
        }

        /*
         * Enter the named type into the internal namespace. We enter the name
         * as we go downward in the parse tree. Any necessary subobjects that
         * involve arguments to the opcode must be created as we go back up the
         * parse tree later.
         */
        status =
            acpi_ns_lookup(walk_state->scope_info, path, object_type,
                   ACPI_IMODE_LOAD_PASS1, flags, walk_state,
                   &node);
        if (ACPI_FAILURE(status)) {
            if (status == AE_ALREADY_EXISTS) {

                /* The name already exists in this scope */

                if (node->flags & ANOBJ_IS_EXTERNAL) {
                    /*
                     * Allow one create on an object or segment that was
                     * previously declared External
                     */
                    node->flags &= ~ANOBJ_IS_EXTERNAL;
                    node->type = (u8) object_type;

                    /* Just retyped a node, probably will need to open a scope */

                    if (acpi_ns_opens_scope(object_type)) {
                        status =
                            acpi_ds_scope_stack_push
                            (node, object_type,
                             walk_state);
                        if (ACPI_FAILURE(status)) {
                            return_ACPI_STATUS
                                (status);
                        }
                    }

                    status = AE_OK;
                }
            }

            if (ACPI_FAILURE(status)) {
                ACPI_ERROR_NAMESPACE(path, status);
                return_ACPI_STATUS(status);
            }
        }
        break;
    }

    /* Common exit */

    if (!op) {

        /* Create a new op */

        op = acpi_ps_alloc_op(walk_state->opcode);
        if (!op) {
            return_ACPI_STATUS(AE_NO_MEMORY);
        }
    }

    /* Initialize the op */

#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
    op->named.path = ACPI_CAST_PTR(u8, path);
#endif

    if (node) {
        /*
         * Put the Node in the "op" object that the parser uses, so we
         * can get it again quickly when this scope is closed
         */
        op->common.node = node;
        op->named.name = node->name.integer;
    }

    acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
               op);
    *out_op = op;
    return_ACPI_STATUS(status);
}
acpi_status
acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
		      union acpi_parse_object *op,
		      struct acpi_namespace_node *method_node,
		      u8 * aml_start,
		      u32 aml_length,
		      struct acpi_evaluate_info *info, u8 pass_number)
{
	acpi_status status;
	struct acpi_parse_state *parser_state = &walk_state->parser_state;
	union acpi_parse_object *extra_op;

	ACPI_FUNCTION_TRACE(ds_init_aml_walk);

	walk_state->parser_state.aml =
	    walk_state->parser_state.aml_start = aml_start;
	walk_state->parser_state.aml_end =
	    walk_state->parser_state.pkg_end = aml_start + aml_length;

	/* The next_op of the next_walk will be the beginning of the method */

	walk_state->next_op = NULL;
	walk_state->pass_number = pass_number;

	if (info) {
		walk_state->params = info->parameters;
		walk_state->caller_return_desc = &info->return_object;
	}

	status = acpi_ps_init_scope(&walk_state->parser_state, op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	if (method_node) {
		walk_state->parser_state.start_node = method_node;
		walk_state->walk_type = ACPI_WALK_METHOD;
		walk_state->method_node = method_node;
		walk_state->method_desc =
		    acpi_ns_get_attached_object(method_node);

		/* 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_ACPI_STATUS(status);
		}

		/* Init the method arguments */

		status = acpi_ds_method_data_init_args(walk_state->params,
						       ACPI_METHOD_NUM_ARGS,
						       walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}
	} else {
		/*
		 * Setup the current scope.
		 * Find a Named Op that has a namespace node associated with it.
		 * search upwards from this Op.  Current scope is the first
		 * Op with a namespace node.
		 */
		extra_op = parser_state->start_op;
		while (extra_op && !extra_op->common.node) {
			extra_op = extra_op->common.parent;
		}

		if (!extra_op) {
			parser_state->start_node = NULL;
		} else {
			parser_state->start_node = extra_op->common.node;
		}

		if (parser_state->start_node) {

			/* Push start scope on scope stack and make it current  */

			status =
			    acpi_ds_scope_stack_push(parser_state->start_node,
						     parser_state->start_node->
						     type, walk_state);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}
	}

	status = acpi_ds_init_callbacks(walk_state, pass_number);
	return_ACPI_STATUS(status);
}
示例#3
0
ACPI_STATUS
acpi_ns_lookup (
	ACPI_GENERIC_STATE      *scope_info,
	NATIVE_CHAR             *pathname,
	OBJECT_TYPE_INTERNAL    type,
	OPERATING_MODE          interpreter_mode,
	u32                     flags,
	ACPI_WALK_STATE         *walk_state,
	ACPI_NAMESPACE_NODE     **return_node)
{
	ACPI_STATUS             status;
	ACPI_NAMESPACE_NODE      *prefix_node;
	ACPI_NAMESPACE_NODE     *current_node = NULL;
	ACPI_NAMESPACE_NODE     *scope_to_push = NULL;
	ACPI_NAMESPACE_NODE     *this_node = NULL;
	u32                     num_segments;
	ACPI_NAME               simple_name;
	u8                      null_name_path = FALSE;
	OBJECT_TYPE_INTERNAL    type_to_check_for;
	OBJECT_TYPE_INTERNAL    this_search_type;

	DEBUG_ONLY_MEMBERS      (u32 i)


	if (!return_node) {
		return (AE_BAD_PARAMETER);
	}


	acpi_gbl_ns_lookup_count++;

	*return_node = ENTRY_NOT_FOUND;


	if (!acpi_gbl_root_node) {
		return (AE_NO_NAMESPACE);
	}

	/*
	 * Get the prefix scope.
	 * A null scope means use the root scope
	 */

	if ((!scope_info) ||
		(!scope_info->scope.node))
	{
		prefix_node = acpi_gbl_root_node;
	}
	else {
		prefix_node = scope_info->scope.node;
	}


	/*
	 * This check is explicitly split provide relax the Type_to_check_for
	 * conditions for Bank_field_defn. Originally, both Bank_field_defn and
	 * Def_field_defn caused Type_to_check_for to be set to ACPI_TYPE_REGION,
	 * but the Bank_field_defn may also check for a Field definition as well
	 * as an Operation_region.
	 */

	if (INTERNAL_TYPE_DEF_FIELD_DEFN == type) {
		/* Def_field_defn defines fields in a Region */

		type_to_check_for = ACPI_TYPE_REGION;
	}

	else if (INTERNAL_TYPE_BANK_FIELD_DEFN == type) {
		/* Bank_field_defn defines data fields in a Field Object */

		type_to_check_for = ACPI_TYPE_ANY;
	}

	else {
		type_to_check_for = type;
	}


	/* TBD: [Restructure] - Move the pathname stuff into a new procedure */

	/* Examine the name pointer */

	if (!pathname) {
		/*  8-12-98 ASL Grammar Update supports null Name_path  */

		null_name_path = TRUE;
		num_segments = 0;
		this_node = acpi_gbl_root_node;

	}

	else {
		/*
		 * Valid name pointer (Internal name format)
		 *
		 * Check for prefixes.  As represented in the AML stream, a
		 * Pathname consists of an optional scope prefix followed by
		 * a segment part.
		 *
		 * If present, the scope prefix is either a Root_prefix (in
		 * which case the name is fully qualified), or zero or more
		 * Parent_prefixes (in which case the name's scope is relative
		 * to the current scope).
		 *
		 * The segment part consists of either:
		 *  - A single 4-byte name segment, or
		 *  - A Dual_name_prefix followed by two 4-byte name segments, or
		 *  - A Multi_name_prefix_op, followed by a byte indicating the
		 *    number of segments and the segments themselves.
		 */

		if (*pathname == AML_ROOT_PREFIX) {
			/* Pathname is fully qualified, look in root name table */

			current_node = acpi_gbl_root_node;

			/* point to segment part */

			pathname++;

			/* Direct reference to root, "\" */

			if (!(*pathname)) {
				this_node = acpi_gbl_root_node;
				goto check_for_new_scope_and_exit;
			}
		}

		else {
			/* Pathname is relative to current scope, start there */

			current_node = prefix_node;

			/*
			 * Handle up-prefix (carat).  More than one prefix
			 * is supported
			 */

			while (*pathname == AML_PARENT_PREFIX) {
				/* Point to segment part or next Parent_prefix */

				pathname++;

				/*  Backup to the parent's scope  */

				this_node = acpi_ns_get_parent_object (current_node);
				if (!this_node) {
					/* Current scope has no parent scope */

					REPORT_ERROR (("Too many parent prefixes (^) - reached root\n"));
					return (AE_NOT_FOUND);
				}

				current_node = this_node;
			}
		}


		/*
		 * Examine the name prefix opcode, if any,
		 * to determine the number of segments
		 */

		if (*pathname == AML_DUAL_NAME_PREFIX) {
			num_segments = 2;

			/* point to first segment */

			pathname++;

		}

		else if (*pathname == AML_MULTI_NAME_PREFIX_OP) {
			num_segments = (u32)* (u8 *) ++pathname;

			/* point to first segment */

			pathname++;

		}

		else {
			/*
			 * No Dual or Multi prefix, hence there is only one
			 * segment and Pathname is already pointing to it.
			 */
			num_segments = 1;

		}

	}


	/*
	 * Search namespace for each segment of the name.
	 * Loop through and verify/add each name segment.
	 */


	while (num_segments-- && current_node) {
		/*
		 * Search for the current name segment under the current
		 * named object.  The Type is significant only at the last (topmost)
		 * level.  (We don't care about the types along the path, only
		 * the type of the final target object.)
		 */
		this_search_type = ACPI_TYPE_ANY;
		if (!num_segments) {
			this_search_type = type;
		}

		/* Pluck one ACPI name from the front of the pathname */

		MOVE_UNALIGNED32_TO_32 (&simple_name, pathname);

		/* Try to find the ACPI name */

		status = acpi_ns_search_and_enter (simple_name, walk_state,
				   current_node, interpreter_mode,
				   this_search_type, flags,
				   &this_node);

		if (ACPI_FAILURE (status)) {
			if (status == AE_NOT_FOUND) {
				/* Name not found in ACPI namespace  */

			}

			return (status);
		}


		/*
		 * If 1) This is the last segment (Num_segments == 0)
		 *    2) and looking for a specific type
		 *       (Not checking for TYPE_ANY)
		 *    3) Which is not an alias
		 *    4) which is not a local type (TYPE_DEF_ANY)
		 *    5) which is not a local type (TYPE_SCOPE)
		 *    6) which is not a local type (TYPE_INDEX_FIELD_DEFN)
		 *    7) and type of object is known (not TYPE_ANY)
		 *    8) and object does not match request
		 *
		 * Then we have a type mismatch.  Just warn and ignore it.
		 */
		if ((num_segments       == 0)                               &&
			(type_to_check_for  != ACPI_TYPE_ANY)                   &&
			(type_to_check_for  != INTERNAL_TYPE_ALIAS)             &&
			(type_to_check_for  != INTERNAL_TYPE_DEF_ANY)           &&
			(type_to_check_for  != INTERNAL_TYPE_SCOPE)             &&
			(type_to_check_for  != INTERNAL_TYPE_INDEX_FIELD_DEFN)  &&
			(this_node->type    != ACPI_TYPE_ANY)                   &&
			(this_node->type    != type_to_check_for))
		{
			/* Complain about a type mismatch */

			REPORT_WARNING (
				("Ns_lookup: %4.4s, type %X, checking for type %X\n",
				&simple_name, this_node->type, type_to_check_for));
		}

		/*
		 * If this is the last name segment and we are not looking for a
		 * specific type, but the type of found object is known, use that type
		 * to see if it opens a scope.
		 */

		if ((0 == num_segments) && (ACPI_TYPE_ANY == type)) {
			type = this_node->type;
		}

		if ((num_segments || acpi_ns_opens_scope (type)) &&
			(this_node->child == NULL))
		{
			/*
			 * More segments or the type implies enclosed scope,
			 * and the next scope has not been allocated.
			 */

		}

		current_node = this_node;

		/* point to next name segment */

		pathname += ACPI_NAME_SIZE;
	}


	/*
	 * Always check if we need to open a new scope
	 */

check_for_new_scope_and_exit:

	if (!(flags & NS_DONT_OPEN_SCOPE) && (walk_state)) {
		/*
		 * If entry is a type which opens a scope,
		 * push the new scope on the scope stack.
		 */

		if (acpi_ns_opens_scope (type_to_check_for)) {
			/*  8-12-98 ASL Grammar Update supports null Name_path  */

			if (null_name_path) {
				/* TBD: [Investigate] - is this the correct thing to do? */

				scope_to_push = NULL;
			}
			else {
				scope_to_push = this_node;
			}

			status = acpi_ds_scope_stack_push (scope_to_push, type,
					   walk_state);
			if (ACPI_FAILURE (status)) {
				return (status);
			}

		}
	}

	*return_node = this_node;
	return (AE_OK);
}
示例#4
0
/*******************************************************************************
 *
 * FUNCTION:    ns_one_complete_parse
 *
 * PARAMETERS:  pass_number             - 1 or 2
 *              table_desc              - The table to be parsed.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
 *
 ******************************************************************************/
acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
			   u32 table_index,
			   struct acpi_namespace_node *start_node)
{
	union acpi_parse_object *parse_root;
	acpi_status status;
       u32 aml_length;
	u8 *aml_start;
	struct acpi_walk_state *walk_state;
	struct acpi_table_header *table;
	acpi_owner_id owner_id;

	ACPI_FUNCTION_TRACE(ns_one_complete_parse);

	status = acpi_tb_get_owner_id(table_index, &owner_id);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Create and init a Root Node */

	parse_root = acpi_ps_create_scope_op();
	if (!parse_root) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
	if (!walk_state) {
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(status);
	}

	/* Table must consist of at least a complete header */

	if (table->length < sizeof(struct acpi_table_header)) {
		status = AE_BAD_HEADER;
	} else {
		aml_start = (u8 *) table + sizeof(struct acpi_table_header);
		aml_length = table->length - sizeof(struct acpi_table_header);
		status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
					       aml_start, aml_length, NULL,
					       (u8) pass_number);
	}

	/* Found OSDT table, enable the namespace override feature */

	if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_OSDT) &&
	    pass_number == ACPI_IMODE_LOAD_PASS1) {
		walk_state->namespace_override = TRUE;
	}

	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		goto cleanup;
	}

	/* start_node is the default location to load the table */

	if (start_node && start_node != acpi_gbl_root_node) {
		status =
		    acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			acpi_ds_delete_walk_state(walk_state);
			goto cleanup;
		}
	}

	/* Parse the AML */

	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %u parse\n",
			  pass_number));
	status = acpi_ps_parse_aml(walk_state);

cleanup:
	acpi_ps_delete_parse_tree(parse_root);
	return_ACPI_STATUS(status);
}
示例#5
0
acpi_status
acpi_ds_load2_begin_op (
	acpi_walk_state         *walk_state,
	acpi_parse_object       **out_op)
{
	acpi_parse_object       *op;
	acpi_namespace_node     *node;
	acpi_status             status;
	acpi_object_type8       data_type;
	NATIVE_CHAR             *buffer_ptr;
	void                    *original = NULL;


	PROC_NAME ("Ds_load2_begin_op");

	op = walk_state->op;
	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));


	if (op) {
		/* We only care about Namespace opcodes here */

		if (!(walk_state->op_info->flags & AML_NSOPCODE) &&
			walk_state->opcode != AML_INT_NAMEPATH_OP) {
			return (AE_OK);
		}

		/* TBD: [Restructure] Temp! same code as in psparse */

		if (!(walk_state->op_info->flags & AML_NAMED)) {
			return (AE_OK);
		}

		/*
		 * Get the name we are going to enter or lookup in the namespace
		 */
		if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
			/* For Namepath op, get the path string */

			buffer_ptr = op->value.string;
			if (!buffer_ptr) {
				/* No name, just exit */

				return (AE_OK);
			}
		}
		else {
			/* Get name from the op */

			buffer_ptr = (NATIVE_CHAR *) &((acpi_parse2_object *)op)->name;
		}
	}
	else {
		buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state);
	}


	/* Map the raw opcode into an internal object type */

	data_type = acpi_ds_map_named_opcode_to_data_type (walk_state->opcode);

	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
		"State=%p Op=%p Type=%x\n", walk_state, op, data_type));


	if (walk_state->opcode == AML_FIELD_OP         ||
		walk_state->opcode == AML_BANK_FIELD_OP    ||
		walk_state->opcode == AML_INDEX_FIELD_OP) {
		node = NULL;
		status = AE_OK;
	}

	else if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
		/*
		 * The Name_path is an object reference to an existing object. Don't enter the
		 * name into the namespace, but look it up for use later
		 */
		status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type,
				  IMODE_EXECUTE, NS_SEARCH_PARENT, walk_state, &(node));
	}

	else {
		if (op && op->node) {
			original = op->node;
			node = op->node;

			if (acpi_ns_opens_scope (data_type)) {
				status = acpi_ds_scope_stack_push (node, data_type, walk_state);
				if (ACPI_FAILURE (status)) {
					return (status);
				}

			}
			return (AE_OK);
		}

		/*
		 * Enter the named type into the internal namespace.  We enter the name
		 * as we go downward in the parse tree.  Any necessary subobjects that involve
		 * arguments to the opcode must be created as we go back up the parse tree later.
		 */
		status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, data_type,
				  IMODE_EXECUTE, NS_NO_UPSEARCH, walk_state, &(node));
	}

	if (ACPI_SUCCESS (status)) {
		if (!op) {
			/* Create a new op */

			op = acpi_ps_alloc_op (walk_state->opcode);
			if (!op) {
				return (AE_NO_MEMORY);
			}

			/* Initialize */

			((acpi_parse2_object *)op)->name = node->name;
			*out_op = op;
		}

		/*
		 * Put the Node in the "op" object that the parser uses, so we
		 * can get it again quickly when this scope is closed
		 */
		op->node = node;

		if (original) {
			ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "old %p new %p\n", original, node));

			if (original != node) {
				ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
					"Lookup match error: old %p new %p\n", original, node));
			}
		}
	}

	return (status);
}
示例#6
0
ACPI_STATUS
acpi_ds_call_control_method (
	ACPI_WALK_LIST          *walk_list,
	ACPI_WALK_STATE         *this_walk_state,
	ACPI_PARSE_OBJECT       *op)
{
	ACPI_STATUS             status;
	ACPI_NAMESPACE_NODE     *method_node;
	ACPI_OPERAND_OBJECT     *obj_desc;
	ACPI_WALK_STATE         *next_walk_state;
	ACPI_PARSE_STATE        *parser_state;
	u32                     i;


	/*
	 * Get the namespace entry for the control method we are about to call
	 */

	method_node = this_walk_state->method_call_node;
	if (!method_node) {
		return (AE_NULL_ENTRY);
	}

	obj_desc = acpi_ns_get_attached_object (method_node);
	if (!obj_desc) {
		return (AE_NULL_OBJECT);
	}


	/* Init for new method, wait on concurrency semaphore */

	status = acpi_ds_begin_method_execution (method_node, obj_desc);
	if (ACPI_FAILURE (status)) {
		return (status);
	}


	/* Create and initialize a new parser state */

	parser_state = acpi_ps_create_state (obj_desc->method.pcode,
			   obj_desc->method.pcode_length);
	if (!parser_state) {
		return (AE_NO_MEMORY);
	}

	acpi_ps_init_scope (parser_state, NULL);
	parser_state->start_node = method_node;


	/* Create a new state for the preempting walk */

	next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
			  NULL, obj_desc, walk_list);
	if (!next_walk_state) {
		/* TBD: delete parser state */

		return (AE_NO_MEMORY);
	}

	next_walk_state->walk_type          = WALK_METHOD;
	next_walk_state->method_node        = method_node;
	next_walk_state->parser_state       = parser_state;
	next_walk_state->parse_flags        = this_walk_state->parse_flags;
	next_walk_state->descending_callback = this_walk_state->descending_callback;
	next_walk_state->ascending_callback = this_walk_state->ascending_callback;

	/* The Next_op of the Next_walk will be the beginning of the method */
	/* TBD: [Restructure] -- obsolete? */

	next_walk_state->next_op = NULL;

	/* Open a new scope */

	status = acpi_ds_scope_stack_push (method_node,
			   ACPI_TYPE_METHOD, next_walk_state);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}


	/*
	 * Initialize the arguments for the method.  The resolved
	 * arguments were put on the previous walk state's operand
	 * stack.  Operands on the previous walk state stack always
	 * start at index 0.
	 */

	status = acpi_ds_method_data_init_args (&this_walk_state->operands[0],
			 this_walk_state->num_operands,
			 next_walk_state);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}


	/* Create and init a Root Node */

	op = acpi_ps_alloc_op (AML_SCOPE_OP);
	if (!op) {
		return (AE_NO_MEMORY);
	}

	status = acpi_ps_parse_aml (op, obj_desc->method.pcode,
			  obj_desc->method.pcode_length,
			  ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE,
			  method_node, NULL, NULL,
			  acpi_ds_load1_begin_op, acpi_ds_load1_end_op);
	acpi_ps_delete_parse_tree (op);


	/*
	 * Delete the operands on the previous walkstate operand stack
	 * (they were copied to new objects)
	 */

	for (i = 0; i < obj_desc->method.param_count; i++) {
		acpi_cm_remove_reference (this_walk_state->operands [i]);
		this_walk_state->operands [i] = NULL;
	}

	/* Clear the operand stack */

	this_walk_state->num_operands = 0;


	return (AE_OK);


	/* On error, we must delete the new walk state */

cleanup:
	acpi_ds_terminate_control_method (next_walk_state);
	acpi_ds_delete_walk_state (next_walk_state);
	return (status);

}
示例#7
0
acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
{
	acpi_status status;
	union acpi_parse_object *op = NULL;
	struct acpi_walk_state *walk_state = NULL;

	ACPI_FUNCTION_TRACE(ps_execute_table);

	/* Create and init a Root Node */

	op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
	if (!op) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	/* Create and initialize a new walk state */

	walk_state =
	    acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
				      NULL, NULL);
	if (!walk_state) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	status = acpi_ds_init_aml_walk(walk_state, op, info->node,
				       info->obj_desc->method.aml_start,
				       info->obj_desc->method.aml_length, info,
				       info->pass_number);
	if (ACPI_FAILURE(status)) {
		goto cleanup;
	}

	if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
		walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
	}

	/* Info->Node is the default location to load the table  */

	if (info->node && info->node != acpi_gbl_root_node) {
		status =
		    acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}
	}

	/*
	 * Parse the AML, walk_state will be deleted by parse_aml
	 */
	acpi_ex_enter_interpreter();
	status = acpi_ps_parse_aml(walk_state);
	acpi_ex_exit_interpreter();
	walk_state = NULL;

cleanup:
	if (walk_state) {
		acpi_ds_delete_walk_state(walk_state);
	}
	if (op) {
		acpi_ps_delete_parse_tree(op);
	}
	return_ACPI_STATUS(status);
}
/*******************************************************************************
 *
 * FUNCTION:    ns_one_complete_parse
 *
 * PARAMETERS:  pass_number             - 1 or 2
 *              table_desc              - The table to be parsed.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
 *
 ******************************************************************************/
acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
			   u32 table_index,
			   struct acpi_namespace_node *start_node)
{
	union acpi_parse_object *parse_root;
	acpi_status status;
       u32 aml_length;
	u8 *aml_start;
	struct acpi_walk_state *walk_state;
	struct acpi_table_header *table;
	acpi_owner_id owner_id;

	ACPI_FUNCTION_TRACE(ns_one_complete_parse);

	status = acpi_tb_get_owner_id(table_index, &owner_id);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Create and init a Root Node */

	parse_root = acpi_ps_create_scope_op();
	if (!parse_root) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Create and initialize a new walk state */

	walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
	if (!walk_state) {
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(status);
	}

	/* Table must consist of at least a complete header */

	if (table->length < sizeof(struct acpi_table_header)) {
		status = AE_BAD_HEADER;
	} else {
		aml_start = (u8 *) table + sizeof(struct acpi_table_header);
		aml_length = table->length - sizeof(struct acpi_table_header);
		status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
					       aml_start, aml_length, NULL,
					       (u8) pass_number);
	}

	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		goto cleanup;
	}

	/* start_node is the default location to load the table */

	if (start_node && start_node != acpi_gbl_root_node) {
		status =
		    acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			acpi_ds_delete_walk_state(walk_state);
			goto cleanup;
		}
	}

	/* Parse the AML */

<<<<<<< HEAD
示例#9
0
acpi_status
acpi_ns_one_complete_parse(u32 pass_number,
			   u32 table_index,
			   struct acpi_namespace_node *start_node)
{
	union acpi_parse_object *parse_root;
	acpi_status status;
       u32 aml_length;
	u8 *aml_start;
	struct acpi_walk_state *walk_state;
	struct acpi_table_header *table;
	acpi_owner_id owner_id;

	ACPI_FUNCTION_TRACE(ns_one_complete_parse);

	status = acpi_tb_get_owner_id(table_index, &owner_id);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*                             */

	parse_root = acpi_ps_create_scope_op();
	if (!parse_root) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/*                                        */

	walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
	if (!walk_state) {
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		acpi_ps_free_op(parse_root);
		return_ACPI_STATUS(status);
	}

	/*                                                  */

	if (table->length < sizeof(struct acpi_table_header)) {
		status = AE_BAD_HEADER;
	} else {
		aml_start = (u8 *) table + sizeof(struct acpi_table_header);
		aml_length = table->length - sizeof(struct acpi_table_header);
		status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
					       aml_start, aml_length, NULL,
					       (u8) pass_number);
	}

	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		goto cleanup;
	}

	/*                                                      */

	if (start_node && start_node != acpi_gbl_root_node) {
		status =
		    acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
					     walk_state);
		if (ACPI_FAILURE(status)) {
			acpi_ds_delete_walk_state(walk_state);
			goto cleanup;
		}
	}

	/*               */

	ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %u parse\n",
			  pass_number));
	status = acpi_ps_parse_aml(walk_state);

      cleanup:
	acpi_ps_delete_parse_tree(parse_root);
	return_ACPI_STATUS(status);
}