root/drivers/acpi/acpica/dsutils.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ds_do_implicit_return
  3. acpi_ds_is_result_used
  4. acpi_ds_delete_result_if_not_used
  5. acpi_ds_resolve_operands
  6. acpi_ds_clear_operands
  7. acpi_ds_create_operand
  8. acpi_ds_create_operands
  9. acpi_ds_evaluate_name_path

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /*******************************************************************************
   3  *
   4  * Module Name: dsutils - Dispatcher utilities
   5  *
   6  ******************************************************************************/
   7 
   8 #include <acpi/acpi.h>
   9 #include "accommon.h"
  10 #include "acparser.h"
  11 #include "amlcode.h"
  12 #include "acdispat.h"
  13 #include "acinterp.h"
  14 #include "acnamesp.h"
  15 #include "acdebug.h"
  16 
  17 #define _COMPONENT          ACPI_DISPATCHER
  18 ACPI_MODULE_NAME("dsutils")
  19 
  20 /*******************************************************************************
  21  *
  22  * FUNCTION:    acpi_ds_clear_implicit_return
  23  *
  24  * PARAMETERS:  walk_state          - Current State
  25  *
  26  * RETURN:      None.
  27  *
  28  * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
  29  *              to delete "stale" return values (if enabled, the return value
  30  *              from every operator is saved at least momentarily, in case the
  31  *              parent method exits.)
  32  *
  33  ******************************************************************************/
  34 void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state)
  35 {
  36         ACPI_FUNCTION_NAME(ds_clear_implicit_return);
  37 
  38         /*
  39          * Slack must be enabled for this feature
  40          */
  41         if (!acpi_gbl_enable_interpreter_slack) {
  42                 return;
  43         }
  44 
  45         if (walk_state->implicit_return_obj) {
  46                 /*
  47                  * Delete any "stale" implicit return. However, in
  48                  * complex statements, the implicit return value can be
  49                  * bubbled up several levels.
  50                  */
  51                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
  52                                   "Removing reference on stale implicit return obj %p\n",
  53                                   walk_state->implicit_return_obj));
  54 
  55                 acpi_ut_remove_reference(walk_state->implicit_return_obj);
  56                 walk_state->implicit_return_obj = NULL;
  57         }
  58 }
  59 
  60 /*******************************************************************************
  61  *
  62  * FUNCTION:    acpi_ds_do_implicit_return
  63  *
  64  * PARAMETERS:  return_desc         - The return value
  65  *              walk_state          - Current State
  66  *              add_reference       - True if a reference should be added to the
  67  *                                    return object
  68  *
  69  * RETURN:      TRUE if implicit return enabled, FALSE otherwise
  70  *
  71  * DESCRIPTION: Implements the optional "implicit return".  We save the result
  72  *              of every ASL operator and control method invocation in case the
  73  *              parent method exit. Before storing a new return value, we
  74  *              delete the previous return value.
  75  *
  76  ******************************************************************************/
  77 
  78 u8
  79 acpi_ds_do_implicit_return(union acpi_operand_object *return_desc,
  80                            struct acpi_walk_state *walk_state, u8 add_reference)
  81 {
  82         ACPI_FUNCTION_NAME(ds_do_implicit_return);
  83 
  84         /*
  85          * Slack must be enabled for this feature, and we must
  86          * have a valid return object
  87          */
  88         if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) {
  89                 return (FALSE);
  90         }
  91 
  92         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
  93                           "Result %p will be implicitly returned; Prev=%p\n",
  94                           return_desc, walk_state->implicit_return_obj));
  95 
  96         /*
  97          * Delete any "stale" implicit return value first. However, in
  98          * complex statements, the implicit return value can be
  99          * bubbled up several levels, so we don't clear the value if it
 100          * is the same as the return_desc.
 101          */
 102         if (walk_state->implicit_return_obj) {
 103                 if (walk_state->implicit_return_obj == return_desc) {
 104                         return (TRUE);
 105                 }
 106                 acpi_ds_clear_implicit_return(walk_state);
 107         }
 108 
 109         /* Save the implicit return value, add a reference if requested */
 110 
 111         walk_state->implicit_return_obj = return_desc;
 112         if (add_reference) {
 113                 acpi_ut_add_reference(return_desc);
 114         }
 115 
 116         return (TRUE);
 117 }
 118 
 119 /*******************************************************************************
 120  *
 121  * FUNCTION:    acpi_ds_is_result_used
 122  *
 123  * PARAMETERS:  op                  - Current Op
 124  *              walk_state          - Current State
 125  *
 126  * RETURN:      TRUE if result is used, FALSE otherwise
 127  *
 128  * DESCRIPTION: Check if a result object will be used by the parent
 129  *
 130  ******************************************************************************/
 131 
 132 u8
 133 acpi_ds_is_result_used(union acpi_parse_object * op,
 134                        struct acpi_walk_state * walk_state)
 135 {
 136         const struct acpi_opcode_info *parent_info;
 137 
 138         ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op);
 139 
 140         /* Must have both an Op and a Result Object */
 141 
 142         if (!op) {
 143                 ACPI_ERROR((AE_INFO, "Null Op"));
 144                 return_UINT8(TRUE);
 145         }
 146 
 147         /*
 148          * We know that this operator is not a
 149          * Return() operator (would not come here.) The following code is the
 150          * optional support for a so-called "implicit return". Some AML code
 151          * assumes that the last value of the method is "implicitly" returned
 152          * to the caller. Just save the last result as the return value.
 153          * NOTE: this is optional because the ASL language does not actually
 154          * support this behavior.
 155          */
 156         (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state,
 157                                          TRUE);
 158 
 159         /*
 160          * Now determine if the parent will use the result
 161          *
 162          * If there is no parent, or the parent is a scope_op, we are executing
 163          * at the method level. An executing method typically has no parent,
 164          * since each method is parsed separately. A method invoked externally
 165          * via execute_control_method has a scope_op as the parent.
 166          */
 167         if ((!op->common.parent) ||
 168             (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
 169 
 170                 /* No parent, the return value cannot possibly be used */
 171 
 172                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 173                                   "At Method level, result of [%s] not used\n",
 174                                   acpi_ps_get_opcode_name(op->common.
 175                                                           aml_opcode)));
 176                 return_UINT8(FALSE);
 177         }
 178 
 179         /* Get info on the parent. The root_op is AML_SCOPE */
 180 
 181         parent_info =
 182             acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode);
 183         if (parent_info->class == AML_CLASS_UNKNOWN) {
 184                 ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op));
 185                 return_UINT8(FALSE);
 186         }
 187 
 188         /*
 189          * Decide what to do with the result based on the parent. If
 190          * the parent opcode will not use the result, delete the object.
 191          * Otherwise leave it as is, it will be deleted when it is used
 192          * as an operand later.
 193          */
 194         switch (parent_info->class) {
 195         case AML_CLASS_CONTROL:
 196 
 197                 switch (op->common.parent->common.aml_opcode) {
 198                 case AML_RETURN_OP:
 199 
 200                         /* Never delete the return value associated with a return opcode */
 201 
 202                         goto result_used;
 203 
 204                 case AML_IF_OP:
 205                 case AML_WHILE_OP:
 206                         /*
 207                          * If we are executing the predicate AND this is the predicate op,
 208                          * we will use the return value
 209                          */
 210                         if ((walk_state->control_state->common.state ==
 211                              ACPI_CONTROL_PREDICATE_EXECUTING) &&
 212                             (walk_state->control_state->control.predicate_op ==
 213                              op)) {
 214                                 goto result_used;
 215                         }
 216                         break;
 217 
 218                 default:
 219 
 220                         /* Ignore other control opcodes */
 221 
 222                         break;
 223                 }
 224 
 225                 /* The general control opcode returns no result */
 226 
 227                 goto result_not_used;
 228 
 229         case AML_CLASS_CREATE:
 230                 /*
 231                  * These opcodes allow term_arg(s) as operands and therefore
 232                  * the operands can be method calls. The result is used.
 233                  */
 234                 goto result_used;
 235 
 236         case AML_CLASS_NAMED_OBJECT:
 237 
 238                 if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
 239                     (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
 240                     || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
 241                     || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
 242                     || (op->common.parent->common.aml_opcode ==
 243                         AML_VARIABLE_PACKAGE_OP)
 244                     || (op->common.parent->common.aml_opcode ==
 245                         AML_INT_EVAL_SUBTREE_OP)
 246                     || (op->common.parent->common.aml_opcode ==
 247                         AML_BANK_FIELD_OP)) {
 248                         /*
 249                          * These opcodes allow term_arg(s) as operands and therefore
 250                          * the operands can be method calls. The result is used.
 251                          */
 252                         goto result_used;
 253                 }
 254 
 255                 goto result_not_used;
 256 
 257         default:
 258                 /*
 259                  * In all other cases. the parent will actually use the return
 260                  * object, so keep it.
 261                  */
 262                 goto result_used;
 263         }
 264 
 265 result_used:
 266         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 267                           "Result of [%s] used by Parent [%s] Op=%p\n",
 268                           acpi_ps_get_opcode_name(op->common.aml_opcode),
 269                           acpi_ps_get_opcode_name(op->common.parent->common.
 270                                                   aml_opcode), op));
 271 
 272         return_UINT8(TRUE);
 273 
 274 result_not_used:
 275         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 276                           "Result of [%s] not used by Parent [%s] Op=%p\n",
 277                           acpi_ps_get_opcode_name(op->common.aml_opcode),
 278                           acpi_ps_get_opcode_name(op->common.parent->common.
 279                                                   aml_opcode), op));
 280 
 281         return_UINT8(FALSE);
 282 }
 283 
 284 /*******************************************************************************
 285  *
 286  * FUNCTION:    acpi_ds_delete_result_if_not_used
 287  *
 288  * PARAMETERS:  op              - Current parse Op
 289  *              result_obj      - Result of the operation
 290  *              walk_state      - Current state
 291  *
 292  * RETURN:      Status
 293  *
 294  * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
 295  *              result descriptor, check if the parent opcode will actually use
 296  *              this result. If not, delete the result now so that it will
 297  *              not become orphaned.
 298  *
 299  ******************************************************************************/
 300 
 301 void
 302 acpi_ds_delete_result_if_not_used(union acpi_parse_object *op,
 303                                   union acpi_operand_object *result_obj,
 304                                   struct acpi_walk_state *walk_state)
 305 {
 306         union acpi_operand_object *obj_desc;
 307         acpi_status status;
 308 
 309         ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj);
 310 
 311         if (!op) {
 312                 ACPI_ERROR((AE_INFO, "Null Op"));
 313                 return_VOID;
 314         }
 315 
 316         if (!result_obj) {
 317                 return_VOID;
 318         }
 319 
 320         if (!acpi_ds_is_result_used(op, walk_state)) {
 321 
 322                 /* Must pop the result stack (obj_desc should be equal to result_obj) */
 323 
 324                 status = acpi_ds_result_pop(&obj_desc, walk_state);
 325                 if (ACPI_SUCCESS(status)) {
 326                         acpi_ut_remove_reference(result_obj);
 327                 }
 328         }
 329 
 330         return_VOID;
 331 }
 332 
 333 /*******************************************************************************
 334  *
 335  * FUNCTION:    acpi_ds_resolve_operands
 336  *
 337  * PARAMETERS:  walk_state          - Current walk state with operands on stack
 338  *
 339  * RETURN:      Status
 340  *
 341  * DESCRIPTION: Resolve all operands to their values. Used to prepare
 342  *              arguments to a control method invocation (a call from one
 343  *              method to another.)
 344  *
 345  ******************************************************************************/
 346 
 347 acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state)
 348 {
 349         u32 i;
 350         acpi_status status = AE_OK;
 351 
 352         ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state);
 353 
 354         /*
 355          * Attempt to resolve each of the valid operands
 356          * Method arguments are passed by reference, not by value. This means
 357          * that the actual objects are passed, not copies of the objects.
 358          */
 359         for (i = 0; i < walk_state->num_operands; i++) {
 360                 status =
 361                     acpi_ex_resolve_to_value(&walk_state->operands[i],
 362                                              walk_state);
 363                 if (ACPI_FAILURE(status)) {
 364                         break;
 365                 }
 366         }
 367 
 368         return_ACPI_STATUS(status);
 369 }
 370 
 371 /*******************************************************************************
 372  *
 373  * FUNCTION:    acpi_ds_clear_operands
 374  *
 375  * PARAMETERS:  walk_state          - Current walk state with operands on stack
 376  *
 377  * RETURN:      None
 378  *
 379  * DESCRIPTION: Clear all operands on the current walk state operand stack.
 380  *
 381  ******************************************************************************/
 382 
 383 void acpi_ds_clear_operands(struct acpi_walk_state *walk_state)
 384 {
 385         u32 i;
 386 
 387         ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state);
 388 
 389         /* Remove a reference on each operand on the stack */
 390 
 391         for (i = 0; i < walk_state->num_operands; i++) {
 392                 /*
 393                  * Remove a reference to all operands, including both
 394                  * "Arguments" and "Targets".
 395                  */
 396                 acpi_ut_remove_reference(walk_state->operands[i]);
 397                 walk_state->operands[i] = NULL;
 398         }
 399 
 400         walk_state->num_operands = 0;
 401         return_VOID;
 402 }
 403 
 404 /*******************************************************************************
 405  *
 406  * FUNCTION:    acpi_ds_create_operand
 407  *
 408  * PARAMETERS:  walk_state      - Current walk state
 409  *              arg             - Parse object for the argument
 410  *              arg_index       - Which argument (zero based)
 411  *
 412  * RETURN:      Status
 413  *
 414  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
 415  *              opcode to the equivalent interpreter object. This may include
 416  *              looking up a name or entering a new name into the internal
 417  *              namespace.
 418  *
 419  ******************************************************************************/
 420 
 421 acpi_status
 422 acpi_ds_create_operand(struct acpi_walk_state *walk_state,
 423                        union acpi_parse_object *arg, u32 arg_index)
 424 {
 425         acpi_status status = AE_OK;
 426         char *name_string;
 427         u32 name_length;
 428         union acpi_operand_object *obj_desc;
 429         union acpi_parse_object *parent_op;
 430         u16 opcode;
 431         acpi_interpreter_mode interpreter_mode;
 432         const struct acpi_opcode_info *op_info;
 433 
 434         ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg);
 435 
 436         /* A valid name must be looked up in the namespace */
 437 
 438         if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
 439             (arg->common.value.string) &&
 440             !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
 441                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n",
 442                                   arg));
 443 
 444                 /* Get the entire name string from the AML stream */
 445 
 446                 status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
 447                                                  arg->common.value.buffer,
 448                                                  &name_string, &name_length);
 449 
 450                 if (ACPI_FAILURE(status)) {
 451                         return_ACPI_STATUS(status);
 452                 }
 453 
 454                 /* All prefixes have been handled, and the name is in name_string */
 455 
 456                 /*
 457                  * Special handling for buffer_field declarations. This is a deferred
 458                  * opcode that unfortunately defines the field name as the last
 459                  * parameter instead of the first. We get here when we are performing
 460                  * the deferred execution, so the actual name of the field is already
 461                  * in the namespace. We don't want to attempt to look it up again
 462                  * because we may be executing in a different scope than where the
 463                  * actual opcode exists.
 464                  */
 465                 if ((walk_state->deferred_node) &&
 466                     (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
 467                     && (arg_index == (u32)
 468                         ((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
 469                         obj_desc =
 470                             ACPI_CAST_PTR(union acpi_operand_object,
 471                                           walk_state->deferred_node);
 472                         status = AE_OK;
 473                 } else {        /* All other opcodes */
 474 
 475                         /*
 476                          * Differentiate between a namespace "create" operation
 477                          * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
 478                          * IMODE_EXECUTE) in order to support the creation of
 479                          * namespace objects during the execution of control methods.
 480                          */
 481                         parent_op = arg->common.parent;
 482                         op_info =
 483                             acpi_ps_get_opcode_info(parent_op->common.
 484                                                     aml_opcode);
 485 
 486                         if ((op_info->flags & AML_NSNODE) &&
 487                             (parent_op->common.aml_opcode !=
 488                              AML_INT_METHODCALL_OP)
 489                             && (parent_op->common.aml_opcode != AML_REGION_OP)
 490                             && (parent_op->common.aml_opcode !=
 491                                 AML_INT_NAMEPATH_OP)) {
 492 
 493                                 /* Enter name into namespace if not found */
 494 
 495                                 interpreter_mode = ACPI_IMODE_LOAD_PASS2;
 496                         } else {
 497                                 /* Return a failure if name not found */
 498 
 499                                 interpreter_mode = ACPI_IMODE_EXECUTE;
 500                         }
 501 
 502                         status =
 503                             acpi_ns_lookup(walk_state->scope_info, name_string,
 504                                            ACPI_TYPE_ANY, interpreter_mode,
 505                                            ACPI_NS_SEARCH_PARENT |
 506                                            ACPI_NS_DONT_OPEN_SCOPE, walk_state,
 507                                            ACPI_CAST_INDIRECT_PTR(struct
 508                                                                   acpi_namespace_node,
 509                                                                   &obj_desc));
 510                         /*
 511                          * The only case where we pass through (ignore) a NOT_FOUND
 512                          * error is for the cond_ref_of opcode.
 513                          */
 514                         if (status == AE_NOT_FOUND) {
 515                                 if (parent_op->common.aml_opcode ==
 516                                     AML_CONDITIONAL_REF_OF_OP) {
 517                                         /*
 518                                          * For the Conditional Reference op, it's OK if
 519                                          * the name is not found;  We just need a way to
 520                                          * indicate this to the interpreter, set the
 521                                          * object to the root
 522                                          */
 523                                         obj_desc =
 524                                             ACPI_CAST_PTR(union
 525                                                                  acpi_operand_object,
 526                                                                  acpi_gbl_root_node);
 527                                         status = AE_OK;
 528                                 } else if (parent_op->common.aml_opcode ==
 529                                            AML_EXTERNAL_OP) {
 530                                         /*
 531                                          * This opcode should never appear here. It is used only
 532                                          * by AML disassemblers and is surrounded by an If(0)
 533                                          * by the ASL compiler.
 534                                          *
 535                                          * Therefore, if we see it here, it is a serious error.
 536                                          */
 537                                         status = AE_AML_BAD_OPCODE;
 538                                 } else {
 539                                         /*
 540                                          * We just plain didn't find it -- which is a
 541                                          * very serious error at this point
 542                                          */
 543                                         status = AE_AML_NAME_NOT_FOUND;
 544                                 }
 545                         }
 546 
 547                         if (ACPI_FAILURE(status)) {
 548                                 ACPI_ERROR_NAMESPACE(walk_state->scope_info,
 549                                                      name_string, status);
 550                         }
 551                 }
 552 
 553                 /* Free the namestring created above */
 554 
 555                 ACPI_FREE(name_string);
 556 
 557                 /* Check status from the lookup */
 558 
 559                 if (ACPI_FAILURE(status)) {
 560                         return_ACPI_STATUS(status);
 561                 }
 562 
 563                 /* Put the resulting object onto the current object stack */
 564 
 565                 status = acpi_ds_obj_stack_push(obj_desc, walk_state);
 566                 if (ACPI_FAILURE(status)) {
 567                         return_ACPI_STATUS(status);
 568                 }
 569 
 570                 acpi_db_display_argument_object(obj_desc, walk_state);
 571         } else {
 572                 /* Check for null name case */
 573 
 574                 if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
 575                     !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
 576                         /*
 577                          * If the name is null, this means that this is an
 578                          * optional result parameter that was not specified
 579                          * in the original ASL. Create a Zero Constant for a
 580                          * placeholder. (Store to a constant is a Noop.)
 581                          */
 582                         opcode = AML_ZERO_OP;   /* Has no arguments! */
 583 
 584                         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 585                                           "Null namepath: Arg=%p\n", arg));
 586                 } else {
 587                         opcode = arg->common.aml_opcode;
 588                 }
 589 
 590                 /* Get the object type of the argument */
 591 
 592                 op_info = acpi_ps_get_opcode_info(opcode);
 593                 if (op_info->object_type == ACPI_TYPE_INVALID) {
 594                         return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
 595                 }
 596 
 597                 if ((op_info->flags & AML_HAS_RETVAL) ||
 598                     (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
 599                         /*
 600                          * Use value that was already previously returned
 601                          * by the evaluation of this argument
 602                          */
 603                         status = acpi_ds_result_pop(&obj_desc, walk_state);
 604                         if (ACPI_FAILURE(status)) {
 605                                 /*
 606                                  * Only error is underflow, and this indicates
 607                                  * a missing or null operand!
 608                                  */
 609                                 ACPI_EXCEPTION((AE_INFO, status,
 610                                                 "Missing or null operand"));
 611                                 return_ACPI_STATUS(status);
 612                         }
 613                 } else {
 614                         /* Create an ACPI_INTERNAL_OBJECT for the argument */
 615 
 616                         obj_desc =
 617                             acpi_ut_create_internal_object(op_info->
 618                                                            object_type);
 619                         if (!obj_desc) {
 620                                 return_ACPI_STATUS(AE_NO_MEMORY);
 621                         }
 622 
 623                         /* Initialize the new object */
 624 
 625                         status =
 626                             acpi_ds_init_object_from_op(walk_state, arg, opcode,
 627                                                         &obj_desc);
 628                         if (ACPI_FAILURE(status)) {
 629                                 acpi_ut_delete_object_desc(obj_desc);
 630                                 return_ACPI_STATUS(status);
 631                         }
 632                 }
 633 
 634                 /* Put the operand object on the object stack */
 635 
 636                 status = acpi_ds_obj_stack_push(obj_desc, walk_state);
 637                 if (ACPI_FAILURE(status)) {
 638                         return_ACPI_STATUS(status);
 639                 }
 640 
 641                 acpi_db_display_argument_object(obj_desc, walk_state);
 642         }
 643 
 644         return_ACPI_STATUS(AE_OK);
 645 }
 646 
 647 /*******************************************************************************
 648  *
 649  * FUNCTION:    acpi_ds_create_operands
 650  *
 651  * PARAMETERS:  walk_state          - Current state
 652  *              first_arg           - First argument of a parser argument tree
 653  *
 654  * RETURN:      Status
 655  *
 656  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
 657  *              namespace objects and place those argument object on the object
 658  *              stack in preparation for evaluation by the interpreter.
 659  *
 660  ******************************************************************************/
 661 
 662 acpi_status
 663 acpi_ds_create_operands(struct acpi_walk_state *walk_state,
 664                         union acpi_parse_object *first_arg)
 665 {
 666         acpi_status status = AE_OK;
 667         union acpi_parse_object *arg;
 668         union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
 669         u32 arg_count = 0;
 670         u32 index = walk_state->num_operands;
 671         u32 i;
 672 
 673         ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);
 674 
 675         /* Get all arguments in the list */
 676 
 677         arg = first_arg;
 678         while (arg) {
 679                 if (index >= ACPI_OBJ_NUM_OPERANDS) {
 680                         return_ACPI_STATUS(AE_BAD_DATA);
 681                 }
 682 
 683                 arguments[index] = arg;
 684                 walk_state->operands[index] = NULL;
 685 
 686                 /* Move on to next argument, if any */
 687 
 688                 arg = arg->common.next;
 689                 arg_count++;
 690                 index++;
 691         }
 692 
 693         ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 694                           "NumOperands %d, ArgCount %d, Index %d\n",
 695                           walk_state->num_operands, arg_count, index));
 696 
 697         /* Create the interpreter arguments, in reverse order */
 698 
 699         index--;
 700         for (i = 0; i < arg_count; i++) {
 701                 arg = arguments[index];
 702                 walk_state->operand_index = (u8)index;
 703 
 704                 status = acpi_ds_create_operand(walk_state, arg, index);
 705                 if (ACPI_FAILURE(status)) {
 706                         goto cleanup;
 707                 }
 708 
 709                 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
 710                                   "Created Arg #%u (%p) %u args total\n",
 711                                   index, arg, arg_count));
 712                 index--;
 713         }
 714 
 715         return_ACPI_STATUS(status);
 716 
 717 cleanup:
 718         /*
 719          * We must undo everything done above; meaning that we must
 720          * pop everything off of the operand stack and delete those
 721          * objects
 722          */
 723         acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
 724 
 725         ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %u", index));
 726         return_ACPI_STATUS(status);
 727 }
 728 
 729 /*****************************************************************************
 730  *
 731  * FUNCTION:    acpi_ds_evaluate_name_path
 732  *
 733  * PARAMETERS:  walk_state      - Current state of the parse tree walk,
 734  *                                the opcode of current operation should be
 735  *                                AML_INT_NAMEPATH_OP
 736  *
 737  * RETURN:      Status
 738  *
 739  * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent
 740  *              interpreter object, convert it to value, if needed, duplicate
 741  *              it, if needed, and push it onto the current result stack.
 742  *
 743  ****************************************************************************/
 744 
 745 acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
 746 {
 747         acpi_status status = AE_OK;
 748         union acpi_parse_object *op = walk_state->op;
 749         union acpi_operand_object **operand = &walk_state->operands[0];
 750         union acpi_operand_object *new_obj_desc;
 751         u8 type;
 752 
 753         ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state);
 754 
 755         if (!op->common.parent) {
 756 
 757                 /* This happens after certain exception processing */
 758 
 759                 goto exit;
 760         }
 761 
 762         if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
 763             (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP) ||
 764             (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
 765 
 766                 /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
 767 
 768                 goto exit;
 769         }
 770 
 771         status = acpi_ds_create_operand(walk_state, op, 0);
 772         if (ACPI_FAILURE(status)) {
 773                 goto exit;
 774         }
 775 
 776         if (op->common.flags & ACPI_PARSEOP_TARGET) {
 777                 new_obj_desc = *operand;
 778                 goto push_result;
 779         }
 780 
 781         type = (*operand)->common.type;
 782 
 783         status = acpi_ex_resolve_to_value(operand, walk_state);
 784         if (ACPI_FAILURE(status)) {
 785                 goto exit;
 786         }
 787 
 788         if (type == ACPI_TYPE_INTEGER) {
 789 
 790                 /* It was incremented by acpi_ex_resolve_to_value */
 791 
 792                 acpi_ut_remove_reference(*operand);
 793 
 794                 status =
 795                     acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc,
 796                                                     walk_state);
 797                 if (ACPI_FAILURE(status)) {
 798                         goto exit;
 799                 }
 800         } else {
 801                 /*
 802                  * The object either was anew created or is
 803                  * a Namespace node - don't decrement it.
 804                  */
 805                 new_obj_desc = *operand;
 806         }
 807 
 808         /* Cleanup for name-path operand */
 809 
 810         status = acpi_ds_obj_stack_pop(1, walk_state);
 811         if (ACPI_FAILURE(status)) {
 812                 walk_state->result_obj = new_obj_desc;
 813                 goto exit;
 814         }
 815 
 816 push_result:
 817 
 818         walk_state->result_obj = new_obj_desc;
 819 
 820         status = acpi_ds_result_push(walk_state->result_obj, walk_state);
 821         if (ACPI_SUCCESS(status)) {
 822 
 823                 /* Force to take it from stack */
 824 
 825                 op->common.flags |= ACPI_PARSEOP_IN_STACK;
 826         }
 827 
 828 exit:
 829 
 830         return_ACPI_STATUS(status);
 831 }

/* [<][>][^][v][top][bottom][index][help] */