ChangeSet 1.1938.505.27, 2005/03/09 23:46:24-05:00, [EMAIL PROTECTED]
[ACPI] ACPICA 20050309 from Bob Moore
The string-to-buffer implicit conversion code has been
modified again after a change to the ACPI specification.
In order to match the behavior of the other major ACPI
implementation, the target buffer is no longer truncated
if the source string is smaller than an existing target
buffer. This change requires an update to the ACPI spec,
and should eliminate the recent AE_AML_BUFFER_LIMIT issues.
The "implicit return" support was rewritten to a new
algorithm that solves the general case. Rather than
attempt to determine when a method is about to exit,
the result of every ASL operator is saved momentarily
until the very next ASL operator is executed. Therefore,
no matter how the method exits, there will always be a
saved implicit return value. This feature is only enabled
with the acpi_gbl_enable_interpreter_slack flag which
Linux enables unless "acpi=strict". This should
eliminate AE_AML_NO_RETURN_VALUE errors.
Implemented implicit conversion support for the predicate
(operand) of the If, Else, and While operators. String and
Buffer arguments are automatically converted to Integers.
Changed the string-to-integer conversion behavior to match
the new ACPI errata: "If no integer object exists, a new
integer is created. The ASCII string is interpreted as a
hexadecimal constant. Each string character is interpreted
as a hexadecimal value ('0'-'9', 'A'-'F', 'a', 'f'),
starting with the first character as the most significant
digit, and ending with the first non-hexadecimal character
or end-of-string." This means that the first non-hex
character terminates the conversion and this is the code
that was changed.
Fixed a problem where the ObjectType operator would fail
(fault) when used on an Index of a Package which pointed
to a null package element. The operator now properly
returns zero (Uninitialized) in this case.
Fixed a problem where the While operator used excessive
memory by not properly popping the result stack during
execution. There was no memory leak after execution,
however. (Code provided by Valery Podrezov.)
Fixed a problem where references to control methods within
Package objects caused the method to be invoked, instead
of producing a reference object pointing to the method.
Restructured and simplified the pswalk.c module
(acpi_ps_delete_parse_tree) to improve performance and reduce
code size. (Code provided by Alexey Starikovskiy.)
Signed-off-by: Len Brown <[EMAIL PROTECTED]>
drivers/acpi/dispatcher/dsmethod.c | 11 +
drivers/acpi/dispatcher/dsopcode.c | 8 +
drivers/acpi/dispatcher/dsutils.c | 166 +++++++++++++++++++-----
drivers/acpi/dispatcher/dswexec.c | 61 ++++++--
drivers/acpi/executer/exmisc.c | 5
drivers/acpi/executer/exresolv.c | 6
drivers/acpi/executer/exstoren.c | 7 -
drivers/acpi/executer/exstorob.c | 27 ++-
drivers/acpi/parser/psparse.c | 42 ++++--
drivers/acpi/parser/pswalk.c | 254 ++++---------------------------------
drivers/acpi/utilities/utcopy.c | 19 ++
drivers/acpi/utilities/utmisc.c | 24 ++-
include/acpi/acconfig.h | 2
include/acpi/acdispat.h | 10 +
include/acpi/acinterp.h | 1
include/acpi/acstruct.h | 1
16 files changed, 330 insertions(+), 314 deletions(-)
diff -Nru a/drivers/acpi/dispatcher/dsmethod.c
b/drivers/acpi/dispatcher/dsmethod.c
--- a/drivers/acpi/dispatcher/dsmethod.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/dispatcher/dsmethod.c 2005-04-01 08:17:32 -08:00
@@ -448,7 +448,16 @@
*/
walk_state->return_desc = return_desc;
}
- else {
+
+ /*
+ * The following code is the
+ * optional support for a so-called "implicit return". Some AML
code
+ * assumes that the last value of the method is "implicitly"
returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not
actually
+ * support this behavior.
+ */
+ else if (!acpi_ds_do_implicit_return (return_desc, walk_state,
FALSE)) {
/*
* Delete the return value if it will not be used by the
* calling method
diff -Nru a/drivers/acpi/dispatcher/dsopcode.c
b/drivers/acpi/dispatcher/dsopcode.c
--- a/drivers/acpi/dispatcher/dsopcode.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/dispatcher/dsopcode.c 2005-04-01 08:17:32 -08:00
@@ -1010,6 +1010,10 @@
* 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);
@@ -1036,6 +1040,10 @@
}
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.
*
diff -Nru a/drivers/acpi/dispatcher/dsutils.c
b/drivers/acpi/dispatcher/dsutils.c
--- a/drivers/acpi/dispatcher/dsutils.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/dispatcher/dsutils.c 2005-04-01 08:17:32 -08:00
@@ -54,10 +54,120 @@
ACPI_MODULE_NAME ("dsutils")
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_clear_implicit_return
+ *
+ * PARAMETERS: walk_state - Current State
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
+ * to delete "stale" return values (if enabled, the return value
+ * from every operator is saved at least momentarily, in case the
+ * parent method exits.)
+ *
+
******************************************************************************/
+
+void
+acpi_ds_clear_implicit_return (
+ struct acpi_walk_state *walk_state)
+{
+ ACPI_FUNCTION_NAME ("ds_clear_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature
+ */
+ if (!acpi_gbl_enable_interpreter_slack) {
+ return;
+ }
+
+ if (walk_state->implicit_return_obj) {
+ /*
+ * Delete any "stale" implicit return. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Removing reference on stale implicit return obj %p\n",
+ walk_state->implicit_return_obj));
+
+ acpi_ut_remove_reference (walk_state->implicit_return_obj);
+ walk_state->implicit_return_obj = NULL;
+ }
+}
+
+
#ifndef ACPI_NO_METHOD_EXECUTION
/*******************************************************************************
*
+ * FUNCTION: acpi_ds_do_implicit_return
+ *
+ * PARAMETERS: return_desc - The return value
+ * walk_state - Current State
+ * add_reference - True if a reference should be added to
the
+ * return object
+ *
+ * RETURN: TRUE if implicit return enabled, FALSE otherwise
+ *
+ * DESCRIPTION: Implements the optional "implicit return". We save the result
+ * of every ASL operator and control method invocation in case the
+ * parent method exit. Before storing a new return value, we
+ * delete the previous return value.
+ *
+
******************************************************************************/
+
+u8
+acpi_ds_do_implicit_return (
+ union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference)
+{
+ ACPI_FUNCTION_NAME ("ds_do_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature, and we must
+ * have a valid return object
+ */
+ if ((!acpi_gbl_enable_interpreter_slack) ||
+ (!return_desc)) {
+ return (FALSE);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Result %p will be implicitly returned; Prev=%p\n",
+ return_desc,
+ walk_state->implicit_return_obj));
+
+ /*
+ * Delete any "stale" implicit return value first. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels, so we don't clear the value if it
+ * is the same as the return_desc.
+ */
+ if (walk_state->implicit_return_obj) {
+ if (walk_state->implicit_return_obj == return_desc) {
+ return (TRUE);
+ }
+ acpi_ds_clear_implicit_return (walk_state);
+ }
+
+ /* Save the implicit return value, add a reference if requested */
+
+ walk_state->implicit_return_obj = return_desc;
+ if (add_reference) {
+ acpi_ut_add_reference (return_desc);
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
* FUNCTION: acpi_ds_is_result_used
*
* PARAMETERS: Op - Current Op
@@ -76,7 +186,6 @@
{
const struct acpi_opcode_info *parent_info;
-
ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
@@ -88,6 +197,19 @@
}
/*
+ * We know that this operator is not a
+ * Return() operator (would not come here.) The following code is the
+ * optional support for a so-called "implicit return". Some AML code
+ * assumes that the last value of the method is "implicitly" returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not actually
+ * support this behavior.
+ */
+ acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE);
+
+ /*
+ * Now determine if the parent will use the result
+ *
* If there is no parent, or the parent is a scope_op, we are executing
* at the method level. An executing method typically has no parent,
* since each method is parsed separately. A method invoked externally
@@ -95,29 +217,10 @@
*/
if ((!op->common.parent) ||
(op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
- /*
- * If this is the last statement in the method, we know it is
not a
- * Return() operator (would not come here.) The following code
is the
- * optional support for a so-called "implicit return". Some AML
code
- * assumes that the last value of the method is "implicitly"
returned
- * to the caller. Just save the last result as the return value.
- * NOTE: this is optional because the ASL language does not
actually
- * support this behavior.
- */
- if ((acpi_gbl_enable_interpreter_slack) &&
- (walk_state->parser_state.aml >=
walk_state->parser_state.aml_end)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
- "Result of [%s] will be implicitly
returned\n",
- acpi_ps_get_opcode_name
(op->common.aml_opcode)));
-
- /* Use the top of the result stack as the implicit
return value */
-
- walk_state->return_desc =
walk_state->results->results.obj_desc[0];
- return_VALUE (TRUE);
- }
-
/* No parent, the return value cannot possibly be used */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result
of [%s] not used\n",
+ acpi_ps_get_opcode_name
(op->common.aml_opcode)));
return_VALUE (FALSE);
}
@@ -262,9 +365,8 @@
}
if (!acpi_ds_is_result_used (op, walk_state)) {
- /*
- * Must pop the result stack (obj_desc should be equal to
result_obj)
- */
+ /* Must pop the result stack (obj_desc should be equal to
result_obj) */
+
status = acpi_ds_result_pop (&obj_desc, walk_state);
if (ACPI_SUCCESS (status)) {
acpi_ut_remove_reference (result_obj);
@@ -338,9 +440,8 @@
ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state);
- /*
- * Remove a reference on each operand on the stack
- */
+ /* Remove a reference on each operand on the stack */
+
for (i = 0; i < walk_state->num_operands; i++) {
/*
* Remove a reference to all operands, including both
@@ -407,11 +508,7 @@
return_ACPI_STATUS (status);
}
- /*
- * All prefixes have been handled, and the name is
- * in name_string
- */
-
+ /* All prefixes have been handled, and the name is in
name_string */
/*
* Special handling for buffer_field declarations. This is a
deferred
@@ -586,7 +683,8 @@
*
* FUNCTION: acpi_ds_create_operands
*
- * PARAMETERS: first_arg - First argument of a parser argument tree
+ * PARAMETERS: walk_state - Current state
+ * first_arg - First argument of a parser argument tree
*
* RETURN: Status
*
diff -Nru a/drivers/acpi/dispatcher/dswexec.c
b/drivers/acpi/dispatcher/dswexec.c
--- a/drivers/acpi/dispatcher/dswexec.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/dispatcher/dswexec.c 2005-04-01 08:17:32 -08:00
@@ -91,6 +91,7 @@
union acpi_operand_object *result_obj) {
acpi_status status = AE_OK;
union acpi_operand_object *obj_desc;
+ union acpi_operand_object *local_obj_desc = NULL;
ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state);
@@ -130,12 +131,17 @@
}
/*
- * Result of predicate evaluation currently must
- * be a number
+ * Result of predicate evaluation must be an Integer
+ * object. Implicitly convert the argument if necessary.
*/
- if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER) {
+ status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Bad predicate (not a number) obj_desc=%p State=%p
Type=%X\n",
+ "Bad predicate (not an integer) obj_desc=%p State=%p
Type=%X\n",
obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc)));
status = AE_AML_OPERAND_TYPE;
@@ -144,13 +150,13 @@
/* Truncate the predicate to 32-bits if necessary */
- acpi_ex_truncate_for32bit_table (obj_desc);
+ acpi_ex_truncate_for32bit_table (local_obj_desc);
/*
* Save the result of the predicate evaluation on
* the control stack
*/
- if (obj_desc->integer.value) {
+ if (local_obj_desc->integer.value) {
walk_state->control_state->common.value = TRUE;
}
else {
@@ -170,12 +176,15 @@
/* Break to debugger to display result */
- ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (obj_desc,
walk_state));
+ ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc,
walk_state));
/*
* Delete the predicate result object (we know that
* we don't need it anymore)
*/
+ if (local_obj_desc != obj_desc) {
+ acpi_ut_remove_reference (local_obj_desc);
+ }
acpi_ut_remove_reference (obj_desc);
walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
@@ -306,9 +315,10 @@
case AML_CLASS_EXECUTE:
case AML_CLASS_CREATE:
- /* most operators with arguments */
- /* Start a new result/operand state */
-
+ /*
+ * Most operators with arguments.
+ * Start a new result/operand state
+ */
status = acpi_ds_result_stack_push (walk_state);
break;
@@ -471,20 +481,41 @@
/* 1 Operand, 0 external_result, 0 internal_result */
status = acpi_ds_exec_end_control_op (walk_state, op);
- if (ACPI_FAILURE (status)) {
- break;
- }
- status = acpi_ds_result_stack_pop (walk_state);
+ /* Make sure to properly pop the result stack */
+
+ if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ }
+ else if (status == AE_CTRL_PENDING) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ if (ACPI_SUCCESS (status)) {
+ status = AE_CTRL_PENDING;
+ }
+ }
break;
case AML_TYPE_METHOD_CALL:
+ /*
+ * If the method is referenced from within a package
+ * declaration, it is not a invocation of the method,
just
+ * a reference to it.
+ */
+ if ((op->asl.parent) &&
+ ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP)
||
+ (op->asl.parent->asl.aml_opcode ==
AML_VAR_PACKAGE_OP))) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method
Reference in a Package, Op=%p\n", op));
+ op->common.node = (struct acpi_namespace_node
*) op->asl.value.arg->asl.node->object;
+ acpi_ut_add_reference
(op->asl.value.arg->asl.node->object);
+ return_ACPI_STATUS (AE_OK);
+ }
+
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method
invocation, Op=%p\n", op));
/*
- * (AML_METHODCALL) Op->Value->Arg->Node contains
+ * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
* the method Node pointer
*/
/* next_op points to the op that holds the method name
*/
diff -Nru a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
--- a/drivers/acpi/executer/exmisc.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/executer/exmisc.c 2005-04-01 08:17:32 -08:00
@@ -95,6 +95,7 @@
switch (obj_desc->reference.opcode) {
case AML_LOCAL_OP:
case AML_ARG_OP:
+ case AML_DEBUG_OP:
/* The referenced object is the pseudo-node for the
local/arg */
@@ -103,7 +104,7 @@
default:
- ACPI_REPORT_ERROR (("Unknown Reference subtype in get
ref %X\n",
+ ACPI_REPORT_ERROR (("Unknown Reference opcode in
get_reference %X\n",
obj_desc->reference.opcode));
return_ACPI_STATUS (AE_AML_INTERNAL);
}
@@ -121,7 +122,7 @@
default:
- ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n",
+ ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference:
%X\n",
ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
return_ACPI_STATUS (AE_TYPE);
}
diff -Nru a/drivers/acpi/executer/exresolv.c b/drivers/acpi/executer/exresolv.c
--- a/drivers/acpi/executer/exresolv.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/executer/exresolv.c 2005-04-01 08:17:32 -08:00
@@ -422,6 +422,12 @@
* This could of course in turn be another reference
object.
*/
obj_desc = *(obj_desc->reference.where);
+ if (!obj_desc) {
+ /* NULL package elements are allowed */
+
+ type = 0; /* Uninitialized */
+ goto exit;
+ }
break;
diff -Nru a/drivers/acpi/executer/exstoren.c b/drivers/acpi/executer/exstoren.c
--- a/drivers/acpi/executer/exstoren.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/executer/exstoren.c 2005-04-01 08:17:32 -08:00
@@ -206,7 +206,6 @@
{
union acpi_operand_object *actual_src_desc;
acpi_status status = AE_OK;
- acpi_object_type original_src_type;
ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc);
@@ -223,8 +222,7 @@
return_ACPI_STATUS (status);
}
- original_src_type = ACPI_GET_OBJECT_TYPE (source_desc);
- if (original_src_type != ACPI_GET_OBJECT_TYPE (dest_desc)) {
+ if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE
(dest_desc)) {
/*
* The source type does not match the type of the destination.
* Perform the "implicit conversion" of the source to the
current type
@@ -275,8 +273,7 @@
* Note: There is different store behavior depending on the
original
* source type
*/
- status = acpi_ex_store_buffer_to_buffer (original_src_type,
actual_src_desc,
- dest_desc);
+ status = acpi_ex_store_buffer_to_buffer (actual_src_desc,
dest_desc);
break;
case ACPI_TYPE_PACKAGE:
diff -Nru a/drivers/acpi/executer/exstorob.c b/drivers/acpi/executer/exstorob.c
--- a/drivers/acpi/executer/exstorob.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/executer/exstorob.c 2005-04-01 08:17:32 -08:00
@@ -66,7 +66,6 @@
acpi_status
acpi_ex_store_buffer_to_buffer (
- acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc)
{
@@ -77,9 +76,8 @@
ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc);
- /*
- * We know that source_desc is a buffer by now
- */
+ /* We know that source_desc is a buffer by now */
+
buffer = (u8 *) source_desc->buffer.pointer;
length = source_desc->buffer.length;
@@ -105,8 +103,17 @@
ACPI_MEMSET (target_desc->buffer.pointer, 0,
target_desc->buffer.length);
ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
-#if ACPI_STRICT_CONFORMANCE
+#ifdef ACPI_OBSOLETE_BEHAVIOR
+ /*
+ * NOTE: ACPI versions up to 3.0 specified that the buffer must
be
+ * truncated if the string is smaller than the buffer.
However, "other"
+ * implementations of ACPI never did this and thus became the
defacto
+ * standard. ACPi 3.0_a changes this behavior such that the
buffer
+ * is no longer truncated.
+ */
+
/*
+ * OBSOLETE BEHAVIOR:
* If the original source was a string, we must truncate the
buffer,
* according to the ACPI spec. Integer-to-Buffer and
Buffer-to-Buffer
* copy must not truncate the original buffer.
@@ -161,9 +168,8 @@
ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc);
- /*
- * We know that source_desc is a string by now.
- */
+ /* We know that source_desc is a string by now */
+
buffer = (u8 *) source_desc->string.pointer;
length = source_desc->string.length;
@@ -187,9 +193,8 @@
*/
if (target_desc->string.pointer &&
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
- /*
- * Only free if not a pointer into the DSDT
- */
+ /* Only free if not a pointer into the DSDT */
+
ACPI_MEM_FREE (target_desc->string.pointer);
}
diff -Nru a/drivers/acpi/parser/psparse.c b/drivers/acpi/parser/psparse.c
--- a/drivers/acpi/parser/psparse.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/parser/psparse.c 2005-04-01 08:17:32 -08:00
@@ -1187,8 +1187,8 @@
previous_walk_state = walk_state;
- ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p, State=%p\n",
- walk_state->return_desc, walk_state));
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "return_value=%p,
implicit_value=%p State=%p\n",
+ walk_state->return_desc,
walk_state->implicit_return_obj, walk_state));
/* Check if we have restarted a preempted walk */
@@ -1200,8 +1200,20 @@
* If the method return value is not used by
the parent,
* The object is deleted
*/
- status = acpi_ds_restart_control_method
(walk_state,
-
previous_walk_state->return_desc);
+ if (!previous_walk_state->return_desc) {
+ status = acpi_ds_restart_control_method
(walk_state,
+
previous_walk_state->implicit_return_obj);
+ }
+ else {
+ /*
+ * We have a valid return value, delete
any implicit
+ * return value.
+ */
+ acpi_ds_clear_implicit_return
(previous_walk_state);
+
+ status = acpi_ds_restart_control_method
(walk_state,
+
previous_walk_state->return_desc);
+ }
if (ACPI_SUCCESS (status)) {
walk_state->walk_type |=
ACPI_WALK_METHOD_RESTART;
}
@@ -1218,12 +1230,26 @@
* value (if any)
*/
else if (previous_walk_state->caller_return_desc) {
- *(previous_walk_state->caller_return_desc) =
previous_walk_state->return_desc; /* NULL if no return value */
+ if (previous_walk_state->implicit_return_obj) {
+ *(previous_walk_state->caller_return_desc) =
previous_walk_state->implicit_return_obj;
+ }
+ else {
+ /* NULL if no return value */
+
+ *(previous_walk_state->caller_return_desc) =
previous_walk_state->return_desc;
+ }
}
- else if (previous_walk_state->return_desc) {
- /* Caller doesn't want it, must delete it */
+ else {
+ if (previous_walk_state->return_desc) {
+ /* Caller doesn't want it, must delete it */
- acpi_ut_remove_reference
(previous_walk_state->return_desc);
+ acpi_ut_remove_reference
(previous_walk_state->return_desc);
+ }
+ if (previous_walk_state->implicit_return_obj) {
+ /* Caller doesn't want it, must delete it */
+
+ acpi_ut_remove_reference
(previous_walk_state->implicit_return_obj);
+ }
}
acpi_ds_delete_walk_state (previous_walk_state);
diff -Nru a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c
--- a/drivers/acpi/parser/pswalk.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/parser/pswalk.c 2005-04-01 08:17:32 -08:00
@@ -44,7 +44,6 @@
#include <acpi/acpi.h>
#include <acpi/acparser.h>
-#include <acpi/acdispat.h>
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME ("pswalk")
@@ -52,256 +51,65 @@
/*******************************************************************************
*
- * FUNCTION: acpi_ps_get_next_walk_op
+ * FUNCTION: acpi_ps_delete_parse_tree
*
- * PARAMETERS: walk_state - Current state of the walk
- * Op - Current Op to be walked
- * ascending_callback - Procedure called when Op is complete
+ * PARAMETERS: subtree_root - Root of tree (or subtree) to delete
*
- * RETURN: Status
+ * RETURN: None
*
- * DESCRIPTION: Get the next Op in a walk of the parse tree.
+ * DESCRIPTION: Delete a portion of or an entire parse tree.
*
******************************************************************************/
-acpi_status
-acpi_ps_get_next_walk_op (
- struct acpi_walk_state *walk_state,
- union acpi_parse_object *op,
- acpi_parse_upwards ascending_callback)
+void
+acpi_ps_delete_parse_tree (
+ union acpi_parse_object *subtree_root)
{
- union acpi_parse_object *next;
- union acpi_parse_object *parent;
- union acpi_parse_object *grand_parent;
- acpi_status status;
+ union acpi_parse_object *op = subtree_root;
+ union acpi_parse_object *next = NULL;
+ union acpi_parse_object *parent = NULL;
- ACPI_FUNCTION_TRACE_PTR ("ps_get_next_walk_op", op);
+ ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
- /* Check for a argument only if we are descending in the tree */
+ /* Visit all nodes in the subtree */
- if (walk_state->next_op_info != ACPI_NEXT_OP_UPWARD) {
- /* Look for an argument or child of the current op */
+ while (op) {
+ /* Check if we are not ascending */
- next = acpi_ps_get_arg (op, 0);
- if (next) {
- /* Still going downward in tree (Op is not completed
yet) */
+ if (op != parent) {
+ /* Look for an argument or child of the current op */
- walk_state->prev_op = op;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
+ next = acpi_ps_get_arg (op, 0);
+ if (next) {
+ /* Still going downward in tree (Op is not
completed yet) */
- return_ACPI_STATUS (AE_OK);
+ op = next;
+ continue;
+ }
}
/*
- * No more children, this Op is complete. Save Next and Parent
- * in case the Op object gets deleted by the callback routine
+ * No more children, this Op is complete.
*/
- next = op->common.next;
- parent = op->common.parent;
+ next = op->common.next;
+ parent = op->common.parent;
- walk_state->op = op;
- walk_state->op_info = acpi_ps_get_opcode_info
(op->common.aml_opcode);
- walk_state->opcode = op->common.aml_opcode;
-
- status = ascending_callback (walk_state);
+ acpi_ps_free_op (op);
/*
* If we are back to the starting point, the walk is complete.
*/
- if (op == walk_state->origin) {
- /* Reached the point of origin, the walk is complete */
-
- walk_state->prev_op = op;
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (status);
+ if (op == subtree_root) {
+ return_VOID;
}
-
- /*
- * Check for a sibling to the current op. A sibling means
- * we are still going "downward" in the tree.
- */
if (next) {
- /* There is a sibling, it will be next */
-
- walk_state->prev_op = op;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- /* Continue downward */
-
- return_ACPI_STATUS (status);
- }
-
- /*
- * Drop into the loop below because we are moving upwards in
- * the tree
- */
- }
- else {
- /*
- * We are resuming a walk, and we were (are) going upward in
the tree.
- * So, we want to drop into the parent loop below.
- */
- parent = op;
- }
-
- /*
- * Look for a sibling of the current Op's parent
- * Continue moving up the tree until we find a node that has not been
- * visited, or we get back to where we started.
- */
- while (parent) {
- /* We are moving up the tree, therefore this parent Op is
complete */
-
- grand_parent = parent->common.parent;
- next = parent->common.next;
-
- walk_state->op = parent;
- walk_state->op_info = acpi_ps_get_opcode_info
(parent->common.aml_opcode);
- walk_state->opcode = parent->common.aml_opcode;
-
- status = ascending_callback (walk_state);
-
- /*
- * If we are back to the starting point, the walk is complete.
- */
- if (parent == walk_state->origin) {
- /* Reached the point of origin, the walk is complete */
-
- walk_state->prev_op = parent;
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (status);
+ op = next;
}
-
- /*
- * If there is a sibling to this parent (it is not the starting
point
- * Op), then we will visit it.
- */
- if (next) {
- /* found sibling of parent */
-
- walk_state->prev_op = parent;
- walk_state->next_op = next;
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- return_ACPI_STATUS (status);
+ else {
+ op = parent;
}
-
- /* No siblings, no errors, just move up one more level in the
tree */
-
- op = parent;
- parent = grand_parent;
- walk_state->prev_op = op;
}
-
-
- /*
- * Got all the way to the top of the tree, we must be done!
- * However, the code should have terminated in the loop above
- */
- walk_state->next_op = NULL;
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_completed_op
- *
- * PARAMETERS: State - Walk state
- * Op - Completed op
- *
- * RETURN: AE_OK
- *
- * DESCRIPTION: Callback function for acpi_ps_get_next_walk_op(). Used during
- * acpi_ps_delete_parse tree to delete Op objects when all
sub-objects
- * have been visited (and deleted.)
- *
-
******************************************************************************/
-
-acpi_status
-acpi_ps_delete_completed_op (
- struct acpi_walk_state *walk_state)
-{
-
- acpi_ps_free_op (walk_state->op);
- return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ps_delete_parse_tree
- *
- * PARAMETERS: subtree_root - Root of tree (or subtree) to delete
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete a portion of or an entire parse tree.
- *
-
******************************************************************************/
-
-void
-acpi_ps_delete_parse_tree (
- union acpi_parse_object *subtree_root)
-{
- struct acpi_walk_state *walk_state;
- struct acpi_thread_state *thread;
- acpi_status status;
-
-
- ACPI_FUNCTION_TRACE_PTR ("ps_delete_parse_tree", subtree_root);
-
-
- if (!subtree_root) {
- return_VOID;
- }
-
- /* Create and initialize a new walk list */
-
- thread = acpi_ut_create_thread_state ();
- if (!thread) {
- return_VOID;
- }
-
- walk_state = acpi_ds_create_walk_state (0, NULL, NULL, thread);
- if (!walk_state) {
- return_VOID;
- }
-
- walk_state->parse_flags = 0;
- walk_state->descending_callback = NULL;
- walk_state->ascending_callback = NULL;
-
- walk_state->origin = subtree_root;
- walk_state->next_op = subtree_root;
-
- /* Head downward in the tree */
-
- walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD;
-
- /* Visit all nodes in the subtree */
-
- while (walk_state->next_op) {
- status = acpi_ps_get_next_walk_op (walk_state,
walk_state->next_op,
- acpi_ps_delete_completed_op);
- if (ACPI_FAILURE (status)) {
- break;
- }
- }
-
- /* We are done with this walk */
-
- acpi_ut_delete_generic_state (ACPI_CAST_PTR (union acpi_generic_state,
thread));
- acpi_ds_delete_walk_state (walk_state);
-
return_VOID;
}
-
-
diff -Nru a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
--- a/drivers/acpi/utilities/utcopy.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/utilities/utcopy.c 2005-04-01 08:17:32 -08:00
@@ -659,15 +659,17 @@
/* Create an actual buffer only if length > 0 */
if (source_desc->buffer.length) {
- dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE
(source_desc->buffer.length);
+ dest_desc->buffer.pointer =
+ ACPI_MEM_ALLOCATE
(source_desc->buffer.length);
if (!dest_desc->buffer.pointer) {
return (AE_NO_MEMORY);
}
/* Copy the actual buffer data */
- ACPI_MEMCPY (dest_desc->buffer.pointer,
source_desc->buffer.pointer,
- source_desc->buffer.length);
+ ACPI_MEMCPY (dest_desc->buffer.pointer,
+ source_desc->buffer.pointer,
+ source_desc->buffer.length);
}
}
break;
@@ -682,7 +684,8 @@
*/
if ((source_desc->string.pointer) &&
(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER)))
{
- dest_desc->string.pointer = ACPI_MEM_ALLOCATE
((acpi_size) source_desc->string.length + 1);
+ dest_desc->string.pointer =
+ ACPI_MEM_ALLOCATE ((acpi_size)
source_desc->string.length + 1);
if (!dest_desc->string.pointer) {
return (AE_NO_MEMORY);
}
@@ -690,6 +693,14 @@
ACPI_MEMCPY (dest_desc->string.pointer,
source_desc->string.pointer,
(acpi_size)
source_desc->string.length + 1);
}
+ break;
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ /*
+ * We copied the reference object, so we now must add a
reference
+ * to the object pointed to by the reference
+ */
+ acpi_ut_add_reference (source_desc->reference.object);
break;
default:
diff -Nru a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
--- a/drivers/acpi/utilities/utmisc.c 2005-04-01 08:17:32 -08:00
+++ b/drivers/acpi/utilities/utmisc.c 2005-04-01 08:17:32 -08:00
@@ -372,7 +372,7 @@
u32 base,
acpi_integer *ret_integer)
{
- u32 this_digit;
+ u32 this_digit = 0;
acpi_integer return_value = 0;
acpi_integer quotient;
@@ -441,23 +441,27 @@
this_digit = ((u8) *string) - '0';
}
else {
+ if (base == 10) {
+ /* Digit is out of range */
+
+ goto error_exit;
+ }
+
this_digit = (u8) ACPI_TOUPPER (*string);
- if (ACPI_IS_UPPER ((char) this_digit)) {
+ if (ACPI_IS_XDIGIT ((char) this_digit)) {
/* Convert ASCII Hex char to value */
this_digit = this_digit - 'A' + 10;
}
else {
- goto error_exit;
+ /*
+ * We allow non-hex chars, just stop now, same
as end-of-string.
+ * See ACPI spec, string-to-integer conversion.
+ */
+ break;
}
}
- /* Check to see if digit is out of range */
-
- if (this_digit >= base) {
- goto error_exit;
- }
-
/* Divide the digit into the correct position */
(void) acpi_ut_short_divide ((ACPI_INTEGER_MAX - (acpi_integer)
this_digit),
@@ -470,6 +474,8 @@
return_value += this_digit;
string++;
}
+
+ /* All done, normal exit */
*ret_integer = return_value;
return_ACPI_STATUS (AE_OK);
diff -Nru a/include/acpi/acconfig.h b/include/acpi/acconfig.h
--- a/include/acpi/acconfig.h 2005-04-01 08:17:32 -08:00
+++ b/include/acpi/acconfig.h 2005-04-01 08:17:32 -08:00
@@ -64,7 +64,7 @@
/* Version string */
-#define ACPI_CA_VERSION 0x20050303
+#define ACPI_CA_VERSION 0x20050309
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
diff -Nru a/include/acpi/acdispat.h b/include/acpi/acdispat.h
--- a/include/acpi/acdispat.h 2005-04-01 08:17:32 -08:00
+++ b/include/acpi/acdispat.h 2005-04-01 08:17:32 -08:00
@@ -374,6 +374,16 @@
/* dsutils - Parser/Interpreter interface utility routines */
+void
+acpi_ds_clear_implicit_return (
+ struct acpi_walk_state *walk_state);
+
+u8
+acpi_ds_do_implicit_return (
+ union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference);
+
u8
acpi_ds_is_result_used (
union acpi_parse_object *op,
diff -Nru a/include/acpi/acinterp.h b/include/acpi/acinterp.h
--- a/include/acpi/acinterp.h 2005-04-01 08:17:32 -08:00
+++ b/include/acpi/acinterp.h 2005-04-01 08:17:32 -08:00
@@ -617,7 +617,6 @@
acpi_status
acpi_ex_store_buffer_to_buffer (
- acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
diff -Nru a/include/acpi/acstruct.h b/include/acpi/acstruct.h
--- a/include/acpi/acstruct.h 2005-04-01 08:17:32 -08:00
+++ b/include/acpi/acstruct.h 2005-04-01 08:17:32 -08:00
@@ -94,6 +94,7 @@
union acpi_generic_state *control_state;
/* List of control states (nested IFs) */
struct acpi_namespace_node *deferred_node;
/* Used when executing deferred opcodes */
struct acpi_gpe_event_info *gpe_event_info;
/* Info for GPE (_Lxx/_Exx methods only */
+ union acpi_operand_object *implicit_return_obj;
struct acpi_namespace_node
local_variables[ACPI_METHOD_NUM_LOCALS]; /* Control method locals */
struct acpi_namespace_node *method_call_node;
/* Called method Node*/
union acpi_parse_object *method_call_op;
/* method_call Op if running a method */
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html