Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /*******************************************************************************
0003  *
0004  * Module Name: dsutils - Dispatcher utilities
0005  *
0006  ******************************************************************************/
0007 
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acparser.h"
0011 #include "amlcode.h"
0012 #include "acdispat.h"
0013 #include "acinterp.h"
0014 #include "acnamesp.h"
0015 #include "acdebug.h"
0016 
0017 #define _COMPONENT          ACPI_DISPATCHER
0018 ACPI_MODULE_NAME("dsutils")
0019 
0020 /*******************************************************************************
0021  *
0022  * FUNCTION:    acpi_ds_clear_implicit_return
0023  *
0024  * PARAMETERS:  walk_state          - Current State
0025  *
0026  * RETURN:      None.
0027  *
0028  * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
0029  *              to delete "stale" return values (if enabled, the return value
0030  *              from every operator is saved at least momentarily, in case the
0031  *              parent method exits.)
0032  *
0033  ******************************************************************************/
0034 void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
0035 {
0036     ACPI_FUNCTION_NAME(ds_clear_implicit_return);
0037 
0038     /*
0039      * Slack must be enabled for this feature
0040      */
0041     if (!acpi_gbl_enable_interpreter_slack) {
0042         return;
0043     }
0044 
0045     if (walk_state->implicit_return_obj) {
0046         /*
0047          * Delete any "stale" implicit return. However, in
0048          * complex statements, the implicit return value can be
0049          * bubbled up several levels.
0050          */
0051         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0052                   "Removing reference on stale implicit return obj %p\n",
0053                   walk_state->implicit_return_obj));
0054 
0055         acpi_ut_remove_reference(walk_state->implicit_return_obj);
0056         walk_state->implicit_return_obj = NULL;
0057     }
0058 }
0059 
0060 /*******************************************************************************
0061  *
0062  * FUNCTION:    acpi_ds_do_implicit_return
0063  *
0064  * PARAMETERS:  return_desc         - The return value
0065  *              walk_state          - Current State
0066  *              add_reference       - True if a reference should be added to the
0067  *                                    return object
0068  *
0069  * RETURN:      TRUE if implicit return enabled, FALSE otherwise
0070  *
0071  * DESCRIPTION: Implements the optional "implicit return".  We save the result
0072  *              of every ASL operator and control method invocation in case the
0073  *              parent method exit. Before storing a new return value, we
0074  *              delete the previous return value.
0075  *
0076  ******************************************************************************/
0077 
0078 u8
0079 acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
0080                struct acpi_walk_state *walk_state, u8 add_reference)
0081 {
0082     ACPI_FUNCTION_NAME(ds_do_implicit_return);
0083 
0084     /*
0085      * Slack must be enabled for this feature, and we must
0086      * have a valid return object
0087      */
0088     if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
0089         return (FALSE);
0090     }
0091 
0092     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0093               "Result %p will be implicitly returned; Prev=%p\n",
0094               return_desc, walk_state->implicit_return_obj));
0095 
0096     /*
0097      * Delete any "stale" implicit return value first. However, in
0098      * complex statements, the implicit return value can be
0099      * bubbled up several levels, so we don't clear the value if it
0100      * is the same as the return_desc.
0101      */
0102     if (walk_state->implicit_return_obj) {
0103         if (walk_state->implicit_return_obj == return_desc) {
0104             return (TRUE);
0105         }
0106         acpi_ds_clear_implicit_return(walk_state);
0107     }
0108 
0109     /* Save the implicit return value, add a reference if requested */
0110 
0111     walk_state->implicit_return_obj = return_desc;
0112     if (add_reference) {
0113         acpi_ut_add_reference(return_desc);
0114     }
0115 
0116     return (TRUE);
0117 }
0118 
0119 /*******************************************************************************
0120  *
0121  * FUNCTION:    acpi_ds_is_result_used
0122  *
0123  * PARAMETERS:  op                  - Current Op
0124  *              walk_state          - Current State
0125  *
0126  * RETURN:      TRUE if result is used, FALSE otherwise
0127  *
0128  * DESCRIPTION: Check if a result object will be used by the parent
0129  *
0130  ******************************************************************************/
0131 
0132 u8
0133 acpi_ds_is_result_used(union acpi_parse_object * op,
0134                struct acpi_walk_state * walk_state)
0135 {
0136     const struct acpi_opcode_info *parent_info;
0137 
0138     ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
0139 
0140     /* Must have both an Op and a Result Object */
0141 
0142     if (!op) {
0143         ACPI_ERROR((AE_INFO, "Null Op"));
0144         return_UINT8(TRUE);
0145     }
0146 
0147     /*
0148      * We know that this operator is not a
0149      * Return() operator (would not come here.) The following code is the
0150      * optional support for a so-called "implicit return". Some AML code
0151      * assumes that the last value of the method is "implicitly" returned
0152      * to the caller. Just save the last result as the return value.
0153      * NOTE: this is optional because the ASL language does not actually
0154      * support this behavior.
0155      */
0156     (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
0157                      TRUE);
0158 
0159     /*
0160      * Now determine if the parent will use the result
0161      *
0162      * If there is no parent, or the parent is a scope_op, we are executing
0163      * at the method level. An executing method typically has no parent,
0164      * since each method is parsed separately. A method invoked externally
0165      * via execute_control_method has a scope_op as the parent.
0166      */
0167     if ((!op->common.parent) ||
0168         (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
0169 
0170         /* No parent, the return value cannot possibly be used */
0171 
0172         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0173                   "At Method level, result of [%s] not used\n",
0174                   acpi_ps_get_opcode_name(op->common.
0175                               aml_opcode)));
0176         return_UINT8(FALSE);
0177     }
0178 
0179     /* Get info on the parent. The root_op is AML_SCOPE */
0180 
0181     parent_info =
0182         acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
0183     if (parent_info->class == AML_CLASS_UNKNOWN) {
0184         ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
0185         return_UINT8(FALSE);
0186     }
0187 
0188     /*
0189      * Decide what to do with the result based on the parent. If
0190      * the parent opcode will not use the result, delete the object.
0191      * Otherwise leave it as is, it will be deleted when it is used
0192      * as an operand later.
0193      */
0194     switch (parent_info->class) {
0195     case AML_CLASS_CONTROL:
0196 
0197         switch (op->common.parent->common.aml_opcode) {
0198         case AML_RETURN_OP:
0199 
0200             /* Never delete the return value associated with a return opcode */
0201 
0202             goto result_used;
0203 
0204         case AML_IF_OP:
0205         case AML_WHILE_OP:
0206             /*
0207              * If we are executing the predicate AND this is the predicate op,
0208              * we will use the return value
0209              */
0210             if ((walk_state->control_state->common.state ==
0211                  ACPI_CONTROL_PREDICATE_EXECUTING) &&
0212                 (walk_state->control_state->control.predicate_op ==
0213                  op)) {
0214                 goto result_used;
0215             }
0216             break;
0217 
0218         default:
0219 
0220             /* Ignore other control opcodes */
0221 
0222             break;
0223         }
0224 
0225         /* The general control opcode returns no result */
0226 
0227         goto result_not_used;
0228 
0229     case AML_CLASS_CREATE:
0230         /*
0231          * These opcodes allow term_arg(s) as operands and therefore
0232          * the operands can be method calls. The result is used.
0233          */
0234         goto result_used;
0235 
0236     case AML_CLASS_NAMED_OBJECT:
0237 
0238         if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
0239             (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
0240             || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
0241             || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
0242             || (op->common.parent->common.aml_opcode ==
0243             AML_VARIABLE_PACKAGE_OP)
0244             || (op->common.parent->common.aml_opcode ==
0245             AML_INT_EVAL_SUBTREE_OP)
0246             || (op->common.parent->common.aml_opcode ==
0247             AML_BANK_FIELD_OP)) {
0248             /*
0249              * These opcodes allow term_arg(s) as operands and therefore
0250              * the operands can be method calls. The result is used.
0251              */
0252             goto result_used;
0253         }
0254 
0255         goto result_not_used;
0256 
0257     default:
0258         /*
0259          * In all other cases. the parent will actually use the return
0260          * object, so keep it.
0261          */
0262         goto result_used;
0263     }
0264 
0265 result_used:
0266     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0267               "Result of [%s] used by Parent [%s] Op=%p\n",
0268               acpi_ps_get_opcode_name(op->common.aml_opcode),
0269               acpi_ps_get_opcode_name(op->common.parent->common.
0270                           aml_opcode), op));
0271 
0272     return_UINT8(TRUE);
0273 
0274 result_not_used:
0275     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0276               "Result of [%s] not used by Parent [%s] Op=%p\n",
0277               acpi_ps_get_opcode_name(op->common.aml_opcode),
0278               acpi_ps_get_opcode_name(op->common.parent->common.
0279                           aml_opcode), op));
0280 
0281     return_UINT8(FALSE);
0282 }
0283 
0284 /*******************************************************************************
0285  *
0286  * FUNCTION:    acpi_ds_delete_result_if_not_used
0287  *
0288  * PARAMETERS:  op              - Current parse Op
0289  *              result_obj      - Result of the operation
0290  *              walk_state      - Current state
0291  *
0292  * RETURN:      Status
0293  *
0294  * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
0295  *              result descriptor, check if the parent opcode will actually use
0296  *              this result. If not, delete the result now so that it will
0297  *              not become orphaned.
0298  *
0299  ******************************************************************************/
0300 
0301 void
0302 acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
0303                   union acpi_operand_object *result_obj,
0304                   struct acpi_walk_state *walk_state)
0305 {
0306     union acpi_operand_object *obj_desc;
0307     acpi_status status;
0308 
0309     ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
0310 
0311     if (!op) {
0312         ACPI_ERROR((AE_INFO, "Null Op"));
0313         return_VOID;
0314     }
0315 
0316     if (!result_obj) {
0317         return_VOID;
0318     }
0319 
0320     if (!acpi_ds_is_result_used(op, walk_state)) {
0321 
0322         /* Must pop the result stack (obj_desc should be equal to result_obj) */
0323 
0324         status = acpi_ds_result_pop(&obj_desc, walk_state);
0325         if (ACPI_SUCCESS(status)) {
0326             acpi_ut_remove_reference(result_obj);
0327         }
0328     }
0329 
0330     return_VOID;
0331 }
0332 
0333 /*******************************************************************************
0334  *
0335  * FUNCTION:    acpi_ds_resolve_operands
0336  *
0337  * PARAMETERS:  walk_state          - Current walk state with operands on stack
0338  *
0339  * RETURN:      Status
0340  *
0341  * DESCRIPTION: Resolve all operands to their values. Used to prepare
0342  *              arguments to a control method invocation (a call from one
0343  *              method to another.)
0344  *
0345  ******************************************************************************/
0346 
0347 acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
0348 {
0349     u32 i;
0350     acpi_status status = AE_OK;
0351 
0352     ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
0353 
0354     /*
0355      * Attempt to resolve each of the valid operands
0356      * Method arguments are passed by reference, not by value. This means
0357      * that the actual objects are passed, not copies of the objects.
0358      */
0359     for (i = 0; i < walk_state->num_operands; i++) {
0360         status =
0361             acpi_ex_resolve_to_value(&walk_state->operands[i],
0362                          walk_state);
0363         if (ACPI_FAILURE(status)) {
0364             break;
0365         }
0366     }
0367 
0368     return_ACPI_STATUS(status);
0369 }
0370 
0371 /*******************************************************************************
0372  *
0373  * FUNCTION:    acpi_ds_clear_operands
0374  *
0375  * PARAMETERS:  walk_state          - Current walk state with operands on stack
0376  *
0377  * RETURN:      None
0378  *
0379  * DESCRIPTION: Clear all operands on the current walk state operand stack.
0380  *
0381  ******************************************************************************/
0382 
0383 void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
0384 {
0385     u32 i;
0386 
0387     ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
0388 
0389     /* Remove a reference on each operand on the stack */
0390 
0391     for (i = 0; i < walk_state->num_operands; i++) {
0392         /*
0393          * Remove a reference to all operands, including both
0394          * "Arguments" and "Targets".
0395          */
0396         acpi_ut_remove_reference(walk_state->operands[i]);
0397         walk_state->operands[i] = NULL;
0398     }
0399 
0400     walk_state->num_operands = 0;
0401     return_VOID;
0402 }
0403 
0404 /*******************************************************************************
0405  *
0406  * FUNCTION:    acpi_ds_create_operand
0407  *
0408  * PARAMETERS:  walk_state      - Current walk state
0409  *              arg             - Parse object for the argument
0410  *              arg_index       - Which argument (zero based)
0411  *
0412  * RETURN:      Status
0413  *
0414  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
0415  *              opcode to the equivalent interpreter object. This may include
0416  *              looking up a name or entering a new name into the internal
0417  *              namespace.
0418  *
0419  ******************************************************************************/
0420 
0421 acpi_status
0422 acpi_ds_create_operand(struct acpi_walk_state *walk_state,
0423                union acpi_parse_object *arg, u32 arg_index)
0424 {
0425     acpi_status status = AE_OK;
0426     char *name_string;
0427     u32 name_length;
0428     union acpi_operand_object *obj_desc;
0429     union acpi_parse_object *parent_op;
0430     u16 opcode;
0431     acpi_interpreter_mode interpreter_mode;
0432     const struct acpi_opcode_info *op_info;
0433 
0434     ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
0435 
0436     /* A valid name must be looked up in the namespace */
0437 
0438     if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
0439         (arg->common.value.string) &&
0440         !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
0441         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
0442                   arg));
0443 
0444         /* Get the entire name string from the AML stream */
0445 
0446         status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
0447                          arg->common.value.buffer,
0448                          &name_string, &name_length);
0449 
0450         if (ACPI_FAILURE(status)) {
0451             return_ACPI_STATUS(status);
0452         }
0453 
0454         /* All prefixes have been handled, and the name is in name_string */
0455 
0456         /*
0457          * Special handling for buffer_field declarations. This is a deferred
0458          * opcode that unfortunately defines the field name as the last
0459          * parameter instead of the first. We get here when we are performing
0460          * the deferred execution, so the actual name of the field is already
0461          * in the namespace. We don't want to attempt to look it up again
0462          * because we may be executing in a different scope than where the
0463          * actual opcode exists.
0464          */
0465         if ((walk_state->deferred_node) &&
0466             (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
0467             && (arg_index == (u32)
0468             ((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
0469             obj_desc =
0470                 ACPI_CAST_PTR(union acpi_operand_object,
0471                       walk_state->deferred_node);
0472             status = AE_OK;
0473         } else {    /* All other opcodes */
0474 
0475             /*
0476              * Differentiate between a namespace "create" operation
0477              * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
0478              * IMODE_EXECUTE) in order to support the creation of
0479              * namespace objects during the execution of control methods.
0480              */
0481             parent_op = arg->common.parent;
0482             op_info =
0483                 acpi_ps_get_opcode_info(parent_op->common.
0484                             aml_opcode);
0485 
0486             if ((op_info->flags & AML_NSNODE) &&
0487                 (parent_op->common.aml_opcode !=
0488                  AML_INT_METHODCALL_OP)
0489                 && (parent_op->common.aml_opcode != AML_REGION_OP)
0490                 && (parent_op->common.aml_opcode !=
0491                 AML_INT_NAMEPATH_OP)) {
0492 
0493                 /* Enter name into namespace if not found */
0494 
0495                 interpreter_mode = ACPI_IMODE_LOAD_PASS2;
0496             } else {
0497                 /* Return a failure if name not found */
0498 
0499                 interpreter_mode = ACPI_IMODE_EXECUTE;
0500             }
0501 
0502             status =
0503                 acpi_ns_lookup(walk_state->scope_info, name_string,
0504                        ACPI_TYPE_ANY, interpreter_mode,
0505                        ACPI_NS_SEARCH_PARENT |
0506                        ACPI_NS_DONT_OPEN_SCOPE, walk_state,
0507                        ACPI_CAST_INDIRECT_PTR(struct
0508                                   acpi_namespace_node,
0509                                   &obj_desc));
0510             /*
0511              * The only case where we pass through (ignore) a NOT_FOUND
0512              * error is for the cond_ref_of opcode.
0513              */
0514             if (status == AE_NOT_FOUND) {
0515                 if (parent_op->common.aml_opcode ==
0516                     AML_CONDITIONAL_REF_OF_OP) {
0517                     /*
0518                      * For the Conditional Reference op, it's OK if
0519                      * the name is not found;  We just need a way to
0520                      * indicate this to the interpreter, set the
0521                      * object to the root
0522                      */
0523                     obj_desc =
0524                         ACPI_CAST_PTR(union
0525                                  acpi_operand_object,
0526                                  acpi_gbl_root_node);
0527                     status = AE_OK;
0528                 } else if (parent_op->common.aml_opcode ==
0529                        AML_EXTERNAL_OP) {
0530                     /*
0531                      * This opcode should never appear here. It is used only
0532                      * by AML disassemblers and is surrounded by an If(0)
0533                      * by the ASL compiler.
0534                      *
0535                      * Therefore, if we see it here, it is a serious error.
0536                      */
0537                     status = AE_AML_BAD_OPCODE;
0538                 } else {
0539                     /*
0540                      * We just plain didn't find it -- which is a
0541                      * very serious error at this point
0542                      */
0543                     status = AE_AML_NAME_NOT_FOUND;
0544                 }
0545             }
0546 
0547             if (ACPI_FAILURE(status)) {
0548                 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
0549                              name_string, status);
0550             }
0551         }
0552 
0553         /* Free the namestring created above */
0554 
0555         ACPI_FREE(name_string);
0556 
0557         /* Check status from the lookup */
0558 
0559         if (ACPI_FAILURE(status)) {
0560             return_ACPI_STATUS(status);
0561         }
0562 
0563         /* Put the resulting object onto the current object stack */
0564 
0565         status = acpi_ds_obj_stack_push(obj_desc, walk_state);
0566         if (ACPI_FAILURE(status)) {
0567             return_ACPI_STATUS(status);
0568         }
0569 
0570         acpi_db_display_argument_object(obj_desc, walk_state);
0571     } else {
0572         /* Check for null name case */
0573 
0574         if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
0575             !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
0576             /*
0577              * If the name is null, this means that this is an
0578              * optional result parameter that was not specified
0579              * in the original ASL. Create a Zero Constant for a
0580              * placeholder. (Store to a constant is a Noop.)
0581              */
0582             opcode = AML_ZERO_OP;   /* Has no arguments! */
0583 
0584             ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0585                       "Null namepath: Arg=%p\n", arg));
0586         } else {
0587             opcode = arg->common.aml_opcode;
0588         }
0589 
0590         /* Get the object type of the argument */
0591 
0592         op_info = acpi_ps_get_opcode_info(opcode);
0593         if (op_info->object_type == ACPI_TYPE_INVALID) {
0594             return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
0595         }
0596 
0597         if ((op_info->flags & AML_HAS_RETVAL) ||
0598             (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
0599             /*
0600              * Use value that was already previously returned
0601              * by the evaluation of this argument
0602              */
0603             status = acpi_ds_result_pop(&obj_desc, walk_state);
0604             if (ACPI_FAILURE(status)) {
0605                 /*
0606                  * Only error is underflow, and this indicates
0607                  * a missing or null operand!
0608                  */
0609                 ACPI_EXCEPTION((AE_INFO, status,
0610                         "Missing or null operand"));
0611                 return_ACPI_STATUS(status);
0612             }
0613         } else {
0614             /* Create an ACPI_INTERNAL_OBJECT for the argument */
0615 
0616             obj_desc =
0617                 acpi_ut_create_internal_object(op_info->
0618                                object_type);
0619             if (!obj_desc) {
0620                 return_ACPI_STATUS(AE_NO_MEMORY);
0621             }
0622 
0623             /* Initialize the new object */
0624 
0625             status =
0626                 acpi_ds_init_object_from_op(walk_state, arg, opcode,
0627                             &obj_desc);
0628             if (ACPI_FAILURE(status)) {
0629                 acpi_ut_delete_object_desc(obj_desc);
0630                 return_ACPI_STATUS(status);
0631             }
0632         }
0633 
0634         /* Put the operand object on the object stack */
0635 
0636         status = acpi_ds_obj_stack_push(obj_desc, walk_state);
0637         if (ACPI_FAILURE(status)) {
0638             return_ACPI_STATUS(status);
0639         }
0640 
0641         acpi_db_display_argument_object(obj_desc, walk_state);
0642     }
0643 
0644     return_ACPI_STATUS(AE_OK);
0645 }
0646 
0647 /*******************************************************************************
0648  *
0649  * FUNCTION:    acpi_ds_create_operands
0650  *
0651  * PARAMETERS:  walk_state          - Current state
0652  *              first_arg           - First argument of a parser argument tree
0653  *
0654  * RETURN:      Status
0655  *
0656  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
0657  *              namespace objects and place those argument object on the object
0658  *              stack in preparation for evaluation by the interpreter.
0659  *
0660  ******************************************************************************/
0661 
0662 acpi_status
0663 acpi_ds_create_operands(struct acpi_walk_state *walk_state,
0664             union acpi_parse_object *first_arg)
0665 {
0666     acpi_status status = AE_OK;
0667     union acpi_parse_object *arg;
0668     union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
0669     u32 arg_count = 0;
0670     u32 index = walk_state->num_operands;
0671     u32 i;
0672 
0673     ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
0674 
0675     /* Get all arguments in the list */
0676 
0677     arg = first_arg;
0678     while (arg) {
0679         if (index >= ACPI_OBJ_NUM_OPERANDS) {
0680             return_ACPI_STATUS(AE_BAD_DATA);
0681         }
0682 
0683         arguments[index] = arg;
0684         walk_state->operands[index] = NULL;
0685 
0686         /* Move on to next argument, if any */
0687 
0688         arg = arg->common.next;
0689         arg_count++;
0690         index++;
0691     }
0692 
0693     ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0694               "NumOperands %d, ArgCount %d, Index %d\n",
0695               walk_state->num_operands, arg_count, index));
0696 
0697     /* Create the interpreter arguments, in reverse order */
0698 
0699     index--;
0700     for (i = 0; i < arg_count; i++) {
0701         arg = arguments[index];
0702         walk_state->operand_index = (u8)index;
0703 
0704         status = acpi_ds_create_operand(walk_state, arg, index);
0705         if (ACPI_FAILURE(status)) {
0706             goto cleanup;
0707         }
0708 
0709         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
0710                   "Created Arg #%u (%p) %u args total\n",
0711                   index, arg, arg_count));
0712         index--;
0713     }
0714 
0715     return_ACPI_STATUS(status);
0716 
0717 cleanup:
0718     /*
0719      * We must undo everything done above; meaning that we must
0720      * pop everything off of the operand stack and delete those
0721      * objects
0722      */
0723     acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
0724 
0725     ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
0726     return_ACPI_STATUS(status);
0727 }
0728 
0729 /*****************************************************************************
0730  *
0731  * FUNCTION:    acpi_ds_evaluate_name_path
0732  *
0733  * PARAMETERS:  walk_state      - Current state of the parse tree walk,
0734  *                                the opcode of current operation should be
0735  *                                AML_INT_NAMEPATH_OP
0736  *
0737  * RETURN:      Status
0738  *
0739  * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
0740  *              interpreter object, convert it to value, if needed, duplicate
0741  *              it, if needed, and push it onto the current result stack.
0742  *
0743  ****************************************************************************/
0744 
0745 acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
0746 {
0747     acpi_status status = AE_OK;
0748     union acpi_parse_object *op = walk_state->op;
0749     union acpi_operand_object **operand = &walk_state->operands[0];
0750     union acpi_operand_object *new_obj_desc;
0751     u8 type;
0752 
0753     ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
0754 
0755     if (!op->common.parent) {
0756 
0757         /* This happens after certain exception processing */
0758 
0759         goto exit;
0760     }
0761 
0762     if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
0763         (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP) ||
0764         (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
0765 
0766         /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
0767 
0768         goto exit;
0769     }
0770 
0771     status = acpi_ds_create_operand(walk_state, op, 0);
0772     if (ACPI_FAILURE(status)) {
0773         goto exit;
0774     }
0775 
0776     if (op->common.flags & ACPI_PARSEOP_TARGET) {
0777         new_obj_desc = *operand;
0778         goto push_result;
0779     }
0780 
0781     type = (*operand)->common.type;
0782 
0783     status = acpi_ex_resolve_to_value(operand, walk_state);
0784     if (ACPI_FAILURE(status)) {
0785         goto exit;
0786     }
0787 
0788     if (type == ACPI_TYPE_INTEGER) {
0789 
0790         /* It was incremented by acpi_ex_resolve_to_value */
0791 
0792         acpi_ut_remove_reference(*operand);
0793 
0794         status =
0795             acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
0796                             walk_state);
0797         if (ACPI_FAILURE(status)) {
0798             goto exit;
0799         }
0800     } else {
0801         /*
0802          * The object either was anew created or is
0803          * a Namespace node - don't decrement it.
0804          */
0805         new_obj_desc = *operand;
0806     }
0807 
0808     /* Cleanup for name-path operand */
0809 
0810     status = acpi_ds_obj_stack_pop(1, walk_state);
0811     if (ACPI_FAILURE(status)) {
0812         walk_state->result_obj = new_obj_desc;
0813         goto exit;
0814     }
0815 
0816 push_result:
0817 
0818     walk_state->result_obj = new_obj_desc;
0819 
0820     status = acpi_ds_result_push(walk_state->result_obj, walk_state);
0821     if (ACPI_SUCCESS(status)) {
0822 
0823         /* Force to take it from stack */
0824 
0825         op->common.flags |= ACPI_PARSEOP_IN_STACK;
0826     }
0827 
0828 exit:
0829 
0830     return_ACPI_STATUS(status);
0831 }