diff options
Diffstat (limited to 'drivers/acpi/acpica/dsopcode.c')
-rw-r--r-- | drivers/acpi/acpica/dsopcode.c | 725 |
1 files changed, 4 insertions, 721 deletions
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index bbecf293aee..c627a288e02 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -1,7 +1,6 @@ /****************************************************************************** * - * Module Name: dsopcode - Dispatcher Op Region support and handling of - * "control" opcodes + * Module Name: dsopcode - Dispatcher suport for regions and fields * *****************************************************************************/ @@ -57,11 +56,6 @@ ACPI_MODULE_NAME("dsopcode") /* Local prototypes */ static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, - struct acpi_namespace_node *scope_node, - u32 aml_length, u8 * aml_start); - -static acpi_status acpi_ds_init_buffer_field(u16 aml_opcode, union acpi_operand_object *obj_desc, union acpi_operand_object *buffer_desc, @@ -71,361 +65,6 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /******************************************************************************* * - * FUNCTION: acpi_ds_execute_arguments - * - * PARAMETERS: Node - Object NS node - * scope_node - Parent NS node - * aml_length - Length of executable AML - * aml_start - Pointer to the AML - * - * RETURN: Status. - * - * DESCRIPTION: Late (deferred) execution of region or field arguments - * - ******************************************************************************/ - -static acpi_status -acpi_ds_execute_arguments(struct acpi_namespace_node *node, - struct acpi_namespace_node *scope_node, - u32 aml_length, u8 * aml_start) -{ - acpi_status status; - union acpi_parse_object *op; - struct acpi_walk_state *walk_state; - - ACPI_FUNCTION_TRACE(ds_execute_arguments); - - /* - * Allocate a new parser op to be the root of the parsed tree - */ - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - /* Save the Node for use in acpi_ps_parse_aml */ - - op->common.node = scope_node; - - /* Create and initialize a new parser state */ - - walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_LOAD_PASS1); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* Mark this parse as a deferred opcode */ - - walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; - walk_state->deferred_node = node; - - /* Pass1: Parse the entire declaration */ - - status = acpi_ps_parse_aml(walk_state); - if (ACPI_FAILURE(status)) { - goto cleanup; - } - - /* Get and init the Op created above */ - - op->common.node = node; - acpi_ps_delete_parse_tree(op); - - /* Evaluate the deferred arguments */ - - op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); - if (!op) { - return_ACPI_STATUS(AE_NO_MEMORY); - } - - op->common.node = scope_node; - - /* Create and initialize a new parser state */ - - walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); - if (!walk_state) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Execute the opcode and arguments */ - - status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, - aml_length, NULL, ACPI_IMODE_EXECUTE); - if (ACPI_FAILURE(status)) { - acpi_ds_delete_walk_state(walk_state); - goto cleanup; - } - - /* Mark this execution as a deferred opcode */ - - walk_state->deferred_node = node; - status = acpi_ps_parse_aml(walk_state); - - cleanup: - acpi_ps_delete_parse_tree(op); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_buffer_field_arguments - * - * PARAMETERS: obj_desc - A valid buffer_field object - * - * RETURN: Status. - * - * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late - * evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) -{ - union acpi_operand_object *extra_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the AML pointer (method object) and buffer_field node */ - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - node = obj_desc->buffer_field.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_BUFFER_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", - acpi_ut_get_node_name(node))); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node->parent, - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_bank_field_arguments - * - * PARAMETERS: obj_desc - A valid bank_field object - * - * RETURN: Status. - * - * DESCRIPTION: Get bank_field bank_value. This implements the late - * evaluation of these field attributes. - * - ******************************************************************************/ - -acpi_status -acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) -{ - union acpi_operand_object *extra_desc; - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the AML pointer (method object) and bank_field node */ - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - node = obj_desc->bank_field.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", - acpi_ut_get_node_name(node))); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node->parent, - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_buffer_arguments - * - * PARAMETERS: obj_desc - A valid Buffer object - * - * RETURN: Status. - * - * DESCRIPTION: Get Buffer length and initializer byte list. This implements - * the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the Buffer node */ - - node = obj_desc->buffer.node; - if (!node) { - ACPI_ERROR((AE_INFO, - "No pointer back to namespace node in buffer object %p", - obj_desc)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node, - obj_desc->buffer.aml_length, - obj_desc->buffer.aml_start); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_get_package_arguments - * - * PARAMETERS: obj_desc - A valid Package object - * - * RETURN: Status. - * - * DESCRIPTION: Get Package length and initializer byte list. This implements - * the late evaluation of these attributes. - * - ******************************************************************************/ - -acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - - ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); - - if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - /* Get the Package node */ - - node = obj_desc->package.node; - if (!node) { - ACPI_ERROR((AE_INFO, - "No pointer back to namespace node in package %p", - obj_desc)); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); - - /* Execute the AML code for the term_arg arguments */ - - status = acpi_ds_execute_arguments(node, node, - obj_desc->package.aml_length, - obj_desc->package.aml_start); - return_ACPI_STATUS(status); -} - -/***************************************************************************** - * - * FUNCTION: acpi_ds_get_region_arguments - * - * PARAMETERS: obj_desc - A valid region object - * - * RETURN: Status. - * - * DESCRIPTION: Get region address and length. This implements the late - * evaluation of these region attributes. - * - ****************************************************************************/ - -acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) -{ - struct acpi_namespace_node *node; - acpi_status status; - union acpi_operand_object *extra_desc; - - ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); - - if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { - return_ACPI_STATUS(AE_OK); - } - - extra_desc = acpi_ns_get_secondary_object(obj_desc); - if (!extra_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); - } - - /* Get the Region node */ - - node = obj_desc->region.node; - - ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname - (ACPI_TYPE_REGION, node, NULL)); - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", - acpi_ut_get_node_name(node), - extra_desc->extra.aml_start)); - - /* Execute the argument AML */ - - status = acpi_ds_execute_arguments(node, node->parent, - extra_desc->extra.aml_length, - extra_desc->extra.aml_start); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Validate the region address/length via the host OS */ - - status = acpi_os_validate_address(obj_desc->region.space_id, - obj_desc->region.address, - (acpi_size) obj_desc->region.length, - acpi_ut_get_node_name(node)); - - if (ACPI_FAILURE(status)) { - /* - * Invalid address/length. We will emit an error message and mark - * the region as invalid, so that it will cause an additional error if - * it is ever used. Then return AE_OK. - */ - ACPI_EXCEPTION((AE_INFO, status, - "During address validation of OpRegion [%4.4s]", - node->name.ascii)); - obj_desc->common.flags |= AOPOBJ_INVALID; - status = AE_OK; - } - - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * * FUNCTION: acpi_ds_initialize_region * * PARAMETERS: obj_handle - Region namespace node @@ -826,8 +465,9 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, * * RETURN: Status * - * DESCRIPTION: Get region address and length - * Called from acpi_ds_exec_end_op during data_table_region parse tree walk + * DESCRIPTION: Get region address and length. + * Called from acpi_ds_exec_end_op during data_table_region parse + * tree walk. * ******************************************************************************/ @@ -1114,360 +754,3 @@ acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, acpi_ut_remove_reference(operand_desc); return_ACPI_STATUS(status); } - -/******************************************************************************* - * - * FUNCTION: acpi_ds_exec_begin_control_op - * - * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op - * - * RETURN: Status - * - * DESCRIPTION: Handles all control ops encountered during control method - * execution. - * - ******************************************************************************/ - -acpi_status -acpi_ds_exec_begin_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_begin_control_op); - - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, - op->common.aml_opcode, walk_state)); - - switch (op->common.aml_opcode) { - case AML_WHILE_OP: - - /* - * If this is an additional iteration of a while loop, continue. - * There is no need to allocate a new control state. - */ - if (walk_state->control_state) { - if (walk_state->control_state->control.aml_predicate_start - == (walk_state->parser_state.aml - 1)) { - - /* Reset the state to start-of-loop */ - - walk_state->control_state->common.state = - ACPI_CONTROL_CONDITIONAL_EXECUTING; - break; - } - } - - /*lint -fallthrough */ - - case AML_IF_OP: - - /* - * IF/WHILE: Create a new control state to manage these - * constructs. We need to manage these as a stack, in order - * to handle nesting. - */ - control_state = acpi_ut_create_control_state(); - if (!control_state) { - status = AE_NO_MEMORY; - break; - } - /* - * Save a pointer to the predicate for multiple executions - * of a loop - */ - control_state->control.aml_predicate_start = - walk_state->parser_state.aml - 1; - control_state->control.package_end = - walk_state->parser_state.pkg_end; - control_state->control.opcode = op->common.aml_opcode; - - /* Push the control state on this walk's control stack */ - - acpi_ut_push_generic_state(&walk_state->control_state, - control_state); - break; - - case AML_ELSE_OP: - - /* Predicate is in the state object */ - /* If predicate is true, the IF was executed, ignore ELSE part */ - - if (walk_state->last_predicate) { - status = AE_CTRL_TRUE; - } - - break; - - case AML_RETURN_OP: - - break; - - default: - break; - } - - return (status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ds_exec_end_control_op - * - * PARAMETERS: walk_list - The list that owns the walk stack - * Op - The control Op - * - * RETURN: Status - * - * DESCRIPTION: Handles all control ops encountered during control method - * execution. - * - ******************************************************************************/ - -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)); - - control_state = walk_state->control_state; - if (control_state->common.value) { - - /* Predicate was true, the body of the loop was just executed */ - - /* - * This loop counter mechanism allows the interpreter to escape - * possibly infinite loops. This can occur in poorly written AML - * when the hardware does not respond within a while loop and the - * loop does not implement a timeout. - */ - control_state->control.loop_count++; - if (control_state->control.loop_count > - ACPI_MAX_LOOP_ITERATIONS) { - status = AE_AML_INFINITE_LOOP; - break; - } - - /* - * Go back and evaluate the predicate and maybe execute the loop - * another time - */ - status = AE_CTRL_PENDING; - walk_state->aml_last_while = - control_state->control.aml_predicate_start; - break; - } - - /* Predicate was false, terminate this while loop */ - - 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); - 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->result_count) { - - /* 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) - && ((walk_state->results->results.obj_desc[0])-> - common.type == ACPI_TYPE_LOCAL_REFERENCE) - && ((walk_state->results->results.obj_desc[0])-> - reference.class != ACPI_REFCLASS_INDEX)) { - 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: - - /* - * Set the single-step flag. This will cause the debugger (if present) - * to break to the console within the AML debugger at the start of the - * next AML instruction. - */ - ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE); - ACPI_DEBUGGER_EXEC(acpi_os_printf - ("**break** Executed AML BreakPoint opcode\n")); - - /* Call to the OSL in case OS wants a piece of the action */ - - status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, - "Executed AML Breakpoint opcode"); - 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=0x%X Op=%p", - op->common.aml_opcode, op)); - - status = AE_AML_BAD_OPCODE; - break; - } - - return (status); -} |