Example #1
0
acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
{
    union acpi_parse_object *op;
    acpi_object_type object_type;
    acpi_status status = AE_OK;

    ACPI_FUNCTION_TRACE(ds_load1_end_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 (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
        return_ACPI_STATUS(AE_OK);
    }

    /* Get the object type to determine if we should pop the scope */

    object_type = walk_state->op_info->object_type;

#ifndef ACPI_NO_METHOD_EXECUTION
    if (walk_state->op_info->flags & AML_FIELD) {
        /*
         * If we are executing a method, do not create any namespace objects
         * during the load phase, only during execution.
         */
        if (!walk_state->method_node) {
            if (walk_state->opcode == AML_FIELD_OP ||
                walk_state->opcode == AML_BANK_FIELD_OP ||
                walk_state->opcode == AML_INDEX_FIELD_OP) {
                status =
                    acpi_ds_init_field_objects(op, walk_state);
            }
        }
        return_ACPI_STATUS(status);
    }

    /*
     * If we are executing a method, do not create any namespace objects
     * during the load phase, only during execution.
     */
    if (!walk_state->method_node) {
        if (op->common.aml_opcode == AML_REGION_OP) {
            status =
                acpi_ex_create_region(op->named.data,
                          op->named.length,
                          (acpi_adr_space_type) ((op->
                                      common.
                                      value.
                                      arg)->
                                     common.
                                     value.
                                     integer),
                          walk_state);
            if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
            }
        } else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
            status =
                acpi_ex_create_region(op->named.data,
                          op->named.length,
                          REGION_DATA_TABLE,
                          walk_state);
            if (ACPI_FAILURE(status)) {
                return_ACPI_STATUS(status);
            }
        }
    }
#endif

    if (op->common.aml_opcode == AML_NAME_OP) {

        /* For Name opcode, get the object type from the argument */

        if (op->common.value.arg) {
            object_type = (acpi_ps_get_opcode_info((op->common.
                                value.arg)->
                                   common.
                                   aml_opcode))->
                object_type;

            /* Set node type if we have a namespace node */

            if (op->common.node) {
                op->common.node->type = (u8) object_type;
            }
        }
    }

    /*
     * If we are executing a method, do not create any namespace objects
     * during the load phase, only during execution.
     */
    if (!walk_state->method_node) {
        if (op->common.aml_opcode == AML_METHOD_OP) {
            /*
             * method_op pkg_length name_string method_flags term_list
             *
             * Note: We must create the method node/object pair as soon as we
             * see the method declaration. This allows later pass1 parsing
             * of invocations of the method (need to know the number of
             * arguments.)
             */
            ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                      "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
                      walk_state, op, op->named.node));

            if (!acpi_ns_get_attached_object(op->named.node)) {
                walk_state->operands[0] =
                    ACPI_CAST_PTR(void, op->named.node);
                walk_state->num_operands = 1;

                status =
                    acpi_ds_create_operands(walk_state,
                                op->common.value.
                                arg);
                if (ACPI_SUCCESS(status)) {
                    status =
                        acpi_ex_create_method(op->named.
                                  data,
                                  op->named.
                                  length,
                                  walk_state);
                }

                walk_state->operands[0] = NULL;
                walk_state->num_operands = 0;

                if (ACPI_FAILURE(status)) {
                    return_ACPI_STATUS(status);
                }
            }
        }
acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object **operand;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
	u32 table_index;
	struct acpi_table_header *table;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);

	/*
	 * This is where we evaluate the Signature string, oem_id string,
	 * and oem_table_id string of the Data Table Region declaration
	 */
	node = op->common.node;

	/* next_op points to Signature string op */

	next_op = op->common.value.arg;

	/*
	 * Evaluate/create the Signature string, oem_id string,
	 * and oem_table_id string operands
	 */
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Resolve the Signature string, oem_id string,
	 * and oem_table_id string operands
	 */
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	operand = &walk_state->operands[0];

	/* Find the ACPI table */

	status = acpi_tb_find_table(operand[0]->string.pointer,
				    operand[1]->string.pointer,
				    operand[2]->string.pointer, &table_index);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	acpi_ut_remove_reference(operand[0]);
	acpi_ut_remove_reference(operand[1]);
	acpi_ut_remove_reference(operand[2]);

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
	obj_desc->region.length = table->length;

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
			  obj_desc->region.length));

	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

	return_ACPI_STATUS(status);
}
acpi_status
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *operand_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);

	/*
	 * This is where we evaluate the address and length fields of the
	 * op_region declaration
	 */
	node = op->common.node;

	/* next_op points to the op that holds the space_ID */

	next_op = op->common.value.arg;

	/* next_op points to address op */

	next_op = next_op->common.next;

	/* Evaluate/create the address and length operands */

	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Resolve the length and address operands to numbers */

	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/*
	 * Get the length operand and save it
	 * (at Top of stack)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 1];

	obj_desc->region.length = (u32) operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);

	/*
	 * Get the address and save it
	 * (at top of stack - 1)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 2];

	obj_desc->region.address = (acpi_physical_address)
	    operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
			  obj_desc->region.length));

	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

	return_ACPI_STATUS(status);
}
acpi_status
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);

	/*
	 * This is where we evaluate the address and length fields of the
	 * create_xxx_field declaration
	 */
	node = op->common.node;

	/* next_op points to the op that holds the Buffer */

	next_op = op->common.value.arg;

	/* Evaluate/create the address and length operands */

	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	/* Resolve the operands */

	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
			    acpi_ps_get_opcode_name(op->common.aml_opcode),
			    status));

		return_ACPI_STATUS(status);
	}

	/* Initialize the Buffer Field */

	if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {

		/* NOTE: Slightly different operands for this opcode */

		status =
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
					      walk_state->operands[0],
					      walk_state->operands[1],
					      walk_state->operands[2],
					      walk_state->operands[3]);
	} else {
		/* All other, create_xxx_field opcodes */

		status =
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
					      walk_state->operands[0],
					      walk_state->operands[1], NULL,
					      walk_state->operands[2]);
	}

	return_ACPI_STATUS(status);
}
acpi_status
acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
			    union acpi_parse_object * op)
{
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;

	ACPI_FUNCTION_NAME(ds_exec_end_control_op);

	switch (op->common.aml_opcode) {
	case AML_IF_OP:

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));

		/*
		 * Save the result of the predicate in case there is an
		 * ELSE to come
		 */
		walk_state->last_predicate =
		    (u8) walk_state->control_state->common.value;

		/*
		 * Pop the control state that was created at the start
		 * of the IF and free it
		 */
		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);
		acpi_ut_delete_generic_state(control_state);
		break;

	case AML_ELSE_OP:

		break;

	case AML_WHILE_OP:

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));

		if (walk_state->control_state->common.value) {

			/* Predicate was true, go back and evaluate it again! */

			status = AE_CTRL_PENDING;
		}

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[WHILE_OP] termination! Op=%p\n", op));

		/* Pop this control state and free it */

		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);

		walk_state->aml_last_while =
		    control_state->control.aml_predicate_start;
		acpi_ut_delete_generic_state(control_state);
		break;

	case AML_RETURN_OP:

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[RETURN_OP] Op=%p Arg=%p\n", op,
				  op->common.value.arg));

		/*
		 * One optional operand -- the return value
		 * It can be either an immediate operand or a result that
		 * has been bubbled up the tree
		 */
		if (op->common.value.arg) {

			/* Since we have a real Return(), delete any implicit return */

			acpi_ds_clear_implicit_return(walk_state);

			/* Return statement has an immediate operand */

			status =
			    acpi_ds_create_operands(walk_state,
						    op->common.value.arg);
			if (ACPI_FAILURE(status)) {
				return (status);
			}

			/*
			 * If value being returned is a Reference (such as
			 * an arg or local), resolve it now because it may
			 * cease to exist at the end of the method.
			 */
			status =
			    acpi_ex_resolve_to_value(&walk_state->operands[0],
						     walk_state);
			if (ACPI_FAILURE(status)) {
				return (status);
			}

			/*
			 * Get the return value and save as the last result
			 * value.  This is the only place where walk_state->return_desc
			 * is set to anything other than zero!
			 */
			walk_state->return_desc = walk_state->operands[0];
		} else if ((walk_state->results) &&
			   (walk_state->results->results.num_results > 0)) {

			/* Since we have a real Return(), delete any implicit return */

			acpi_ds_clear_implicit_return(walk_state);

			/*
			 * The return value has come from a previous calculation.
			 *
			 * If value being returned is a Reference (such as
			 * an arg or local), resolve it now because it may
			 * cease to exist at the end of the method.
			 *
			 * Allow references created by the Index operator to return unchanged.
			 */
			if ((ACPI_GET_DESCRIPTOR_TYPE
			     (walk_state->results->results.obj_desc[0]) ==
			     ACPI_DESC_TYPE_OPERAND)
			    &&
			    (ACPI_GET_OBJECT_TYPE
			     (walk_state->results->results.obj_desc[0]) ==
			     ACPI_TYPE_LOCAL_REFERENCE)
			    && ((walk_state->results->results.obj_desc[0])->
				reference.opcode != AML_INDEX_OP)) {
				status =
				    acpi_ex_resolve_to_value(&walk_state->
							     results->results.
							     obj_desc[0],
							     walk_state);
				if (ACPI_FAILURE(status)) {
					return (status);
				}
			}

			walk_state->return_desc =
			    walk_state->results->results.obj_desc[0];
		} else {
			/* No return operand */

			if (walk_state->num_operands) {
				acpi_ut_remove_reference(walk_state->
							 operands[0]);
			}

			walk_state->operands[0] = NULL;
			walk_state->num_operands = 0;
			walk_state->return_desc = NULL;
		}

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "Completed RETURN_OP State=%p, RetVal=%p\n",
				  walk_state, walk_state->return_desc));

		/* End the control method execution right now */

		status = AE_CTRL_TERMINATE;
		break;

	case AML_NOOP_OP:

		/* Just do nothing! */
		break;

	case AML_BREAK_POINT_OP:

		/* Call up to the OS service layer to handle this */

		status =
		    acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
				   "Executed AML Breakpoint opcode");

		/* If and when it returns, all done. */

		break;

	case AML_BREAK_OP:
	case AML_CONTINUE_OP:	/* ACPI 2.0 */

		/* Pop and delete control states until we find a while */

		while (walk_state->control_state &&
		       (walk_state->control_state->control.opcode !=
			AML_WHILE_OP)) {
			control_state =
			    acpi_ut_pop_generic_state(&walk_state->
						      control_state);
			acpi_ut_delete_generic_state(control_state);
		}

		/* No while found? */

		if (!walk_state->control_state) {
			return (AE_AML_NO_WHILE);
		}

		/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */

		walk_state->aml_last_while =
		    walk_state->control_state->control.package_end;

		/* Return status depending on opcode */

		if (op->common.aml_opcode == AML_BREAK_OP) {
			status = AE_CTRL_BREAK;
		} else {
			status = AE_CTRL_CONTINUE;
		}
		break;

	default:

		ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p",
			    op->common.aml_opcode, op));

		status = AE_AML_BAD_OPCODE;
		break;
	}

	return (status);
}
Example #6
0
acpi_status
acpi_ds_load2_end_op (
	acpi_walk_state         *walk_state)
{
	acpi_parse_object       *op;
	acpi_status             status = AE_OK;
	acpi_object_type8       data_type;
	acpi_namespace_node     *node;
	acpi_parse_object       *arg;
	acpi_namespace_node     *new_node;
	u32                     i;


	PROC_NAME ("Ds_load2_end_op");

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


	/* Only interested in opcodes that have namespace objects */

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

	if (op->opcode == AML_SCOPE_OP) {
		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
			"Ending scope Op=%p State=%p\n", op, walk_state));

		if (((acpi_parse2_object *)op)->name == -1) {
			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unnamed scope! Op=%p State=%p\n",
				op, walk_state));
			return (AE_OK);
		}
	}


	data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);

	/*
	 * Get the Node/name from the earlier lookup
	 * (It was saved in the *op structure)
	 */
	node = op->node;

	/*
	 * Put the Node on the object stack (Contains the ACPI Name of
	 * this object)
	 */
	walk_state->operands[0] = (void *) node;
	walk_state->num_operands = 1;

	/* Pop the scope stack */

	if (acpi_ns_opens_scope (data_type)) {

		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
			acpi_ut_get_type_name (data_type), op));
		acpi_ds_scope_stack_pop (walk_state);
	}

	/*
	 * Named operations are as follows:
	 *
	 * AML_ALIAS
	 * AML_BANKFIELD
	 * AML_CREATEBITFIELD
	 * AML_CREATEBYTEFIELD
	 * AML_CREATEDWORDFIELD
	 * AML_CREATEFIELD
	 * AML_CREATEQWORDFIELD
	 * AML_CREATEWORDFIELD
	 * AML_DATA_REGION
	 * AML_DEVICE
	 * AML_EVENT
	 * AML_FIELD
	 * AML_INDEXFIELD
	 * AML_METHOD
	 * AML_METHODCALL
	 * AML_MUTEX
	 * AML_NAME
	 * AML_NAMEDFIELD
	 * AML_OPREGION
	 * AML_POWERRES
	 * AML_PROCESSOR
	 * AML_SCOPE
	 * AML_THERMALZONE
	 */

	ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
		"Create-Load [%s] State=%p Op=%p Named_obj=%p\n",
		acpi_ps_get_opcode_name (op->opcode), walk_state, op, node));

	/* Decode the opcode */

	arg = op->value.arg;

	switch (walk_state->op_info->type) {
	case AML_TYPE_CREATE_FIELD:

		/*
		 * Create the field object, but the field buffer and index must
		 * be evaluated later during the execution phase
		 */
		status = acpi_ds_create_buffer_field (op, walk_state);
		break;


	 case AML_TYPE_NAMED_FIELD:

		arg = op->value.arg;
		switch (op->opcode) {
		case AML_INDEX_FIELD_OP:

			status = acpi_ds_create_index_field (op, (acpi_handle) arg->node,
					   walk_state);
			break;


		case AML_BANK_FIELD_OP:

			status = acpi_ds_create_bank_field (op, arg->node, walk_state);
			break;


		case AML_FIELD_OP:

			status = acpi_ds_create_field (op, arg->node, walk_state);
			break;
		}
		break;


	 case AML_TYPE_NAMED_SIMPLE:

		status = acpi_ds_create_operands (walk_state, arg);
		if (ACPI_FAILURE (status)) {
			goto cleanup;
		}

		switch (op->opcode) {
		case AML_PROCESSOR_OP:

			status = acpi_ex_create_processor (walk_state);
			break;


		case AML_POWER_RES_OP:

			status = acpi_ex_create_power_resource (walk_state);
			break;


		case AML_MUTEX_OP:

			status = acpi_ex_create_mutex (walk_state);
			break;


		case AML_EVENT_OP:

			status = acpi_ex_create_event (walk_state);
			break;


		case AML_DATA_REGION_OP:

			status = acpi_ex_create_table_region (walk_state);
			break;

		case AML_ALIAS_OP:

			status = acpi_ex_create_alias (walk_state);
			break;

		default:
			/* Unknown opcode */

			status = AE_OK;
			goto cleanup;
			break;
		}

		/* Delete operands */

		for (i = 1; i < walk_state->num_operands; i++) {
			acpi_ut_remove_reference (walk_state->operands[i]);
			walk_state->operands[i] = NULL;
		}

		break;


	case AML_TYPE_NAMED_COMPLEX:

		switch (op->opcode) {
		case AML_METHOD_OP:
			/*
			 * Method_op Pkg_length Names_string Method_flags Term_list
			 */
			ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
				"LOADING-Method: State=%p Op=%p Named_obj=%p\n",
				walk_state, op, node));

			if (!node->object) {
				status = acpi_ds_create_operands (walk_state, arg);
				if (ACPI_FAILURE (status)) {
					goto cleanup;
				}

				status = acpi_ex_create_method (((acpi_parse2_object *) op)->data,
						   ((acpi_parse2_object *) op)->length,
						   walk_state);
			}
			break;


		case AML_REGION_OP:
			/*
			 * The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
			 * (We must save the address of the AML of the address and length operands)
			 */
			status = acpi_ex_create_region (((acpi_parse2_object *) op)->data,
					  ((acpi_parse2_object *) op)->length,
							 (ACPI_ADR_SPACE_TYPE) arg->value.integer, walk_state);
			break;


		case AML_NAME_OP:

			status = acpi_ds_create_node (walk_state, node, op);
			break;
		}
		break;


	case AML_CLASS_INTERNAL:

		/* case AML_INT_NAMEPATH_OP: */
		break;


	case AML_CLASS_METHOD_CALL:

		ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
			"RESOLVING-Method_call: State=%p Op=%p Named_obj=%p\n",
			walk_state, op, node));

		/*
		 * Lookup the method name and save the Node
		 */
		status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
				  ACPI_TYPE_ANY, IMODE_LOAD_PASS2,
				  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
				  walk_state, &(new_node));
		if (ACPI_SUCCESS (status)) {
			/* TBD: has name already been resolved by here ??*/

			/* TBD: [Restructure] Make sure that what we found is indeed a method! */
			/* We didn't search for a method on purpose, to see if the name would resolve! */

			/* We could put the returned object (Node) on the object stack for later, but
			 * for now, we will put it in the "op" object that the parser uses, so we
			 * can get it again at the end of this scope
			 */
			op->node = new_node;
		}

		break;


	default:
		break;
	}


cleanup:

	/* Remove the Node pushed at the very beginning */

	walk_state->operands[0] = NULL;
	walk_state->num_operands = 0;
	return (status);
}