예제 #1
0
static acpi_status
acpi_ds_create_external_region(acpi_status lookup_status,
			       union acpi_parse_object *op,
			       char *path,
			       struct acpi_walk_state *walk_state,
			       struct acpi_namespace_node **node)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;

	if (lookup_status != AE_NOT_FOUND) {
		return (lookup_status);
	}

	/*
	 * Table disassembly:
	 * operation_region not found. Generate an External for it, and
	 * insert the name into the namespace.
	 */
	acpi_dm_add_to_external_list(op, path, ACPI_TYPE_REGION, 0);
	status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
				ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
				walk_state, node);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/* Must create and install a region object for the new node */

	obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
	if (!obj_desc) {
		return (AE_NO_MEMORY);
	}

	obj_desc->region.node = *node;
	status = acpi_ns_attach_object(*node, obj_desc, ACPI_TYPE_REGION);
	return (status);
}
예제 #2
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);
}