acpi_status acpi_ds_eval_bank_field_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; union acpi_parse_object *arg; ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); /* * This is where we evaluate the bank_value field of the * bank_field declaration */ /* next_op points to the op that holds the Region */ next_op = op->common.value.arg; /* next_op points to the op that holds the Bank Register */ next_op = next_op->common.next; /* next_op points to the op that holds the Bank Value */ next_op = next_op->common.next; /* * Set proper index into operand stack for acpi_ds_obj_stack_push * invoked inside acpi_ds_create_operand. * * We use walk_state->Operands[0] to store the evaluated bank_value */ walk_state->operand_index = 0; status = acpi_ds_create_operand(walk_state, next_op, 0); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, acpi_ps_get_opcode_name(op->common.aml_opcode), 1); /* * Get the bank_value operand and save it * (at Top of stack) */ operand_desc = walk_state->operands[0]; /* Arg points to the start Bank Field */ arg = acpi_ps_get_arg(op, 4); while (arg) { /* Ignore OFFSET and ACCESSAS terms here */ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { node = arg->common.node; obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return_ACPI_STATUS(AE_NOT_EXIST); } obj_desc->bank_field.value = (u32) operand_desc->integer.value; } /* Move to next field in the list */ arg = arg->common.next; } acpi_ut_remove_reference(operand_desc); return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_ex_resolve_object * * PARAMETERS: source_desc_ptr - Pointer to the source object * target_type - Current type of the target * walk_state - Current walk state * * RETURN: Status, resolved object in source_desc_ptr. * * DESCRIPTION: Resolve an object. If the object is a reference, dereference * it and return the actual object in the source_desc_ptr. * ******************************************************************************/ acpi_status acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr, acpi_object_type target_type, struct acpi_walk_state *walk_state) { union acpi_operand_object *source_desc = *source_desc_ptr; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(ex_resolve_object); /* Ensure we have a Target that can be stored to */ switch (target_type) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* * These cases all require only Integers or values that * can be converted to Integers (Strings or Buffers) */ case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * Stores into a Field/Region or into a Integer/Buffer/String * are all essentially the same. This case handles the * "interchangeable" types Integer, String, and Buffer. */ if (ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) { /* Resolve a reference object first */ status = acpi_ex_resolve_to_value(source_desc_ptr, walk_state); if (ACPI_FAILURE(status)) { break; } } /* For copy_object, no further validation necessary */ if (walk_state->opcode == AML_COPY_OP) { break; } /* Must have a Integer, Buffer, or String */ if ((ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_INTEGER) && (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_BUFFER) && (ACPI_GET_OBJECT_TYPE(source_desc) != ACPI_TYPE_STRING) && !((ACPI_GET_OBJECT_TYPE(source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) { /* Conversion successful but still not a valid type */ ACPI_ERROR((AE_INFO, "Cannot assign type %s to %s (must be type Int/Str/Buf)", acpi_ut_get_object_type_name(source_desc), acpi_ut_get_type_name(target_type))); status = AE_AML_OPERAND_TYPE; } break; case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: /* * All aliases should have been resolved earlier, during the * operand resolution phase. */ ACPI_ERROR((AE_INFO, "Store into an unresolved Alias object")); status = AE_AML_INTERNAL; break; case ACPI_TYPE_PACKAGE: default: /* * All other types than Alias and the various Fields come here, * including the untyped case - ACPI_TYPE_ANY. */ break; } 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); }
acpi_status acpi_ns_get_object_value ( acpi_namespace_node *node, acpi_operand_object **return_obj_desc) { acpi_status status = AE_OK; acpi_operand_object *obj_desc; acpi_operand_object *source_desc; FUNCTION_TRACE ("Ns_get_object_value"); /* * We take the value from certain objects directly */ if ((node->type == ACPI_TYPE_PROCESSOR) || (node->type == ACPI_TYPE_POWER)) { /* * Create a Reference object to contain the object */ obj_desc = acpi_ut_create_internal_object (node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* * Get the attached object */ source_desc = acpi_ns_get_attached_object (node); if (!source_desc) { status = AE_NULL_OBJECT; goto unlock_and_exit; } /* * Just copy from the original to the return object * * TBD: [Future] - need a low-level object copy that handles * the reference count automatically. (Don't want to copy it) */ MEMCPY (obj_desc, source_desc, sizeof (acpi_operand_object)); obj_desc->common.reference_count = 1; acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } /* * Other objects require a reference object wrapper which we * then attempt to resolve. */ else { /* Create an Reference object to contain the object */ obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Construct a descriptor pointing to the name */ obj_desc->reference.opcode = (u8) AML_NAME_OP; obj_desc->reference.object = (void *) node; /* * Use Resolve_to_value() to get the associated value. This call * always deletes Obj_desc (allocated above). * * NOTE: we can get away with passing in NULL for a walk state * because Obj_desc is guaranteed to not be a reference to either * a method local or a method argument * * Even though we do not directly invoke the interpreter * for this, we must enter it because we could access an opregion. * The opregion access code assumes that the interpreter * is locked. * * We must release the namespace lock before entering the * intepreter. */ acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); status = acpi_ex_enter_interpreter (); if (ACPI_SUCCESS (status)) { status = acpi_ex_resolve_to_value (&obj_desc, NULL); acpi_ex_exit_interpreter (); } } /* * If Acpi_ex_resolve_to_value() succeeded, the return value was * placed in Obj_desc. */ if (ACPI_SUCCESS (status)) { status = AE_CTRL_RETURN_VALUE; *return_obj_desc = obj_desc; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Returning obj %p\n", *return_obj_desc)); } /* Namespace is unlocked */ return_ACPI_STATUS (status); unlock_and_exit: /* Unlock the namespace */ acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); }