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); }
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); }