Commit 4e3156b1 authored by Bob Moore's avatar Bob Moore Committed by Len Brown

ACPICA: changed order of interpretation of operand objects

The interpreter now evaluates operands in the order that they
appear (both in the
 AML and ASL), instead of in reverse order. This previously
 caused subtle incompatibilities with the MS interpreter as well
 as being non-intuitive.
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent ba886cd4
...@@ -472,7 +472,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, ...@@ -472,7 +472,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
/* A valid name must be looked up in the namespace */ /* A valid name must be looked up in the namespace */
if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
(arg->common.value.string)) { (arg->common.value.string) &&
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
arg)); arg));
...@@ -595,7 +596,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, ...@@ -595,7 +596,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
} else { } else {
/* Check for null name case */ /* Check for null name case */
if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) { if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
!(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
/* /*
* If the name is null, this means that this is an * If the name is null, this means that this is an
* optional result parameter that was not specified * optional result parameter that was not specified
...@@ -617,7 +619,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, ...@@ -617,7 +619,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(AE_NOT_IMPLEMENTED); return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
} }
if (op_info->flags & AML_HAS_RETVAL) { if ((op_info->flags & AML_HAS_RETVAL)
|| (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Argument previously created, already stacked\n")); "Argument previously created, already stacked\n"));
...@@ -759,3 +762,107 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state, ...@@ -759,3 +762,107 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index));
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/*****************************************************************************
*
* FUNCTION: acpi_ds_evaluate_name_path
*
* PARAMETERS: walk_state - Current state of the parse tree walk,
* the opcode of current operation should be
* AML_INT_NAMEPATH_OP
*
* RETURN: Status
*
* DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
* interpreter object, convert it to value, if needed, duplicate
* it, if needed, and push it onto the current result stack.
*
****************************************************************************/
acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
{
acpi_status status = AE_OK;
union acpi_parse_object *op = walk_state->op;
union acpi_operand_object **operand = &walk_state->operands[0];
union acpi_operand_object *new_obj_desc;
u8 type;
ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
if (!op->common.parent) {
/* This happens after certain exception processing */
goto exit;
}
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
(op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
(op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
/* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
goto exit;
}
status = acpi_ds_create_operand(walk_state, op, 0);
if (ACPI_FAILURE(status)) {
goto exit;
}
if (op->common.flags & ACPI_PARSEOP_TARGET) {
new_obj_desc = *operand;
goto push_result;
}
type = ACPI_GET_OBJECT_TYPE(*operand);
status = acpi_ex_resolve_to_value(operand, walk_state);
if (ACPI_FAILURE(status)) {
goto exit;
}
if (type == ACPI_TYPE_INTEGER) {
/* It was incremented by acpi_ex_resolve_to_value */
acpi_ut_remove_reference(*operand);
status =
acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
walk_state);
if (ACPI_FAILURE(status)) {
goto exit;
}
} else {
/*
* The object either was anew created or is
* a Namespace node - don't decrement it.
*/
new_obj_desc = *operand;
}
/* Cleanup for name-path operand */
status = acpi_ds_obj_stack_pop(1, walk_state);
if (ACPI_FAILURE(status)) {
walk_state->result_obj = new_obj_desc;
goto exit;
}
push_result:
walk_state->result_obj = new_obj_desc;
status = acpi_ds_result_push(walk_state->result_obj, walk_state);
if (ACPI_SUCCESS(status)) {
/* Force to take it from stack */
op->common.flags |= ACPI_PARSEOP_IN_STACK;
}
exit:
return_ACPI_STATUS(status);
}
...@@ -375,10 +375,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) ...@@ -375,10 +375,17 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
/* Decode the Opcode Class */ /* Decode the Opcode Class */
switch (op_class) { switch (op_class) {
case AML_CLASS_ARGUMENT: /* constants, literals, etc. - do nothing */ case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */
if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
status = acpi_ds_evaluate_name_path(walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
}
break; break;
case AML_CLASS_EXECUTE: /* most operators with arguments */ case AML_CLASS_EXECUTE: /* Most operators with arguments */
/* Build resolved operand stack */ /* Build resolved operand stack */
......
...@@ -217,9 +217,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) ...@@ -217,9 +217,10 @@ void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc)
/* /*
* Object must be a valid number and we must be executing * Object must be a valid number and we must be executing
* a control method * a control method. NS node could be there for AML_INT_NAMEPATH_OP.
*/ */
if ((!obj_desc) || if ((!obj_desc) ||
(ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) ||
(ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) { (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_INTEGER)) {
return; return;
} }
......
...@@ -182,6 +182,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state, ...@@ -182,6 +182,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state);
unnamed_op->common.value.arg = NULL; unnamed_op->common.value.arg = NULL;
unnamed_op->common.arg_list_length = 0;
unnamed_op->common.aml_opcode = walk_state->opcode; unnamed_op->common.aml_opcode = walk_state->opcode;
/* /*
...@@ -280,6 +281,9 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, ...@@ -280,6 +281,9 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state,
acpi_status status = AE_OK; acpi_status status = AE_OK;
union acpi_parse_object *op; union acpi_parse_object *op;
union acpi_parse_object *named_op = NULL; union acpi_parse_object *named_op = NULL;
union acpi_parse_object *parent_scope;
u8 argument_count;
const struct acpi_opcode_info *op_info;
ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state);
...@@ -320,8 +324,23 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state, ...@@ -320,8 +324,23 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state,
op->named.length = 0; op->named.length = 0;
} }
acpi_ps_append_arg(acpi_ps_get_parent_scope parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state));
(&(walk_state->parser_state)), op); acpi_ps_append_arg(parent_scope, op);
if (parent_scope) {
op_info =
acpi_ps_get_opcode_info(parent_scope->common.aml_opcode);
if (op_info->flags & AML_HAS_TARGET) {
argument_count =
acpi_ps_get_argument_count(op_info->type);
if (parent_scope->common.arg_list_length >
argument_count) {
op->common.flags |= ACPI_PARSEOP_TARGET;
}
} else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) {
op->common.flags |= ACPI_PARSEOP_TARGET;
}
}
if (walk_state->descending_callback != NULL) { if (walk_state->descending_callback != NULL) {
/* /*
......
...@@ -49,6 +49,8 @@ ...@@ -49,6 +49,8 @@
#define _COMPONENT ACPI_PARSER #define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psopcode") ACPI_MODULE_NAME("psopcode")
const u8 acpi_gbl_argument_count[] = { 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 6 };
/******************************************************************************* /*******************************************************************************
* *
* NAME: acpi_gbl_aml_op_info * NAME: acpi_gbl_aml_op_info
...@@ -59,6 +61,7 @@ ACPI_MODULE_NAME("psopcode") ...@@ -59,6 +61,7 @@ ACPI_MODULE_NAME("psopcode")
* the operand type. * the operand type.
* *
******************************************************************************/ ******************************************************************************/
/* /*
* Summary of opcode types/flags * Summary of opcode types/flags
* *
...@@ -176,6 +179,7 @@ ACPI_MODULE_NAME("psopcode") ...@@ -176,6 +179,7 @@ ACPI_MODULE_NAME("psopcode")
AML_CREATE_QWORD_FIELD_OP AML_CREATE_QWORD_FIELD_OP
******************************************************************************/ ******************************************************************************/
/* /*
* Master Opcode information table. A summary of everything we know about each * Master Opcode information table. A summary of everything we know about each
* opcode, all in one place. * opcode, all in one place.
...@@ -779,3 +783,25 @@ char *acpi_ps_get_opcode_name(u16 opcode) ...@@ -779,3 +783,25 @@ char *acpi_ps_get_opcode_name(u16 opcode)
#endif #endif
} }
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_argument_count
*
* PARAMETERS: op_type - Type associated with the AML opcode
*
* RETURN: Argument count
*
* DESCRIPTION: Obtain the number of expected arguments for an AML opcode
*
******************************************************************************/
u8 acpi_ps_get_argument_count(u32 op_type)
{
if (op_type <= AML_TYPE_EXEC_6A_0T_1R) {
return (acpi_gbl_argument_count[op_type]);
}
return (0);
}
...@@ -171,6 +171,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) ...@@ -171,6 +171,8 @@ acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
while (arg) { while (arg) {
arg->common.parent = op; arg->common.parent = op;
arg = arg->common.next; arg = arg->common.next;
op->common.arg_list_length++;
} }
} }
......
...@@ -269,6 +269,8 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state); ...@@ -269,6 +269,8 @@ acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state);
void acpi_ds_clear_operands(struct acpi_walk_state *walk_state); void acpi_ds_clear_operands(struct acpi_walk_state *walk_state);
acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state);
/* /*
* dswscope - Scope Stack manipulation * dswscope - Scope Stack manipulation
*/ */
......
...@@ -603,6 +603,7 @@ union acpi_parse_value { ...@@ -603,6 +603,7 @@ union acpi_parse_value {
union acpi_parse_object *next; /* Next op */\ union acpi_parse_object *next; /* Next op */\
struct acpi_namespace_node *node; /* For use by interpreter */\ struct acpi_namespace_node *node; /* For use by interpreter */\
union acpi_parse_value value; /* Value or args associated with the opcode */\ union acpi_parse_value value; /* Value or args associated with the opcode */\
u8 arg_list_length; /* Number of elements in the arg list */\
ACPI_DISASM_ONLY_MEMBERS (\ ACPI_DISASM_ONLY_MEMBERS (\
u8 disasm_flags; /* Used during AML disassembly */\ u8 disasm_flags; /* Used during AML disassembly */\
u8 disasm_opcode; /* Subtype used for disassembly */\ u8 disasm_opcode; /* Subtype used for disassembly */\
...@@ -695,6 +696,8 @@ struct acpi_parse_state { ...@@ -695,6 +696,8 @@ struct acpi_parse_state {
#define ACPI_PARSEOP_NAMED 0x02 #define ACPI_PARSEOP_NAMED 0x02
#define ACPI_PARSEOP_DEFERRED 0x04 #define ACPI_PARSEOP_DEFERRED 0x04
#define ACPI_PARSEOP_BYTELIST 0x08 #define ACPI_PARSEOP_BYTELIST 0x08
#define ACPI_PARSEOP_IN_STACK 0x10
#define ACPI_PARSEOP_TARGET 0x20
#define ACPI_PARSEOP_IN_CACHE 0x80 #define ACPI_PARSEOP_IN_CACHE 0x80
/* Parse object disasm_flags */ /* Parse object disasm_flags */
......
...@@ -109,6 +109,8 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode); ...@@ -109,6 +109,8 @@ const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode);
char *acpi_ps_get_opcode_name(u16 opcode); char *acpi_ps_get_opcode_name(u16 opcode);
u8 acpi_ps_get_argument_count(u32 op_type);
/* /*
* psparse - top level parsing routines * psparse - top level parsing routines
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment