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

Reply via email to