linux/drivers/acpi/acpica/dsmthdat.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/*******************************************************************************
   3 *
   4 * Module Name: dsmthdat - control method arguments and local variables
   5 *
   6 ******************************************************************************/
   7
   8#include <acpi/acpi.h>
   9#include "accommon.h"
  10#include "acdispat.h"
  11#include "acnamesp.h"
  12#include "acinterp.h"
  13
  14#define _COMPONENT          ACPI_DISPATCHER
  15ACPI_MODULE_NAME("dsmthdat")
  16
  17/* Local prototypes */
  18static void
  19acpi_ds_method_data_delete_value(u8 type,
  20                                 u32 index, struct acpi_walk_state *walk_state);
  21
  22static acpi_status
  23acpi_ds_method_data_set_value(u8 type,
  24                              u32 index,
  25                              union acpi_operand_object *object,
  26                              struct acpi_walk_state *walk_state);
  27
  28#ifdef ACPI_OBSOLETE_FUNCTIONS
  29acpi_object_type
  30acpi_ds_method_data_get_type(u16 opcode,
  31                             u32 index, struct acpi_walk_state *walk_state);
  32#endif
  33
  34/*******************************************************************************
  35 *
  36 * FUNCTION:    acpi_ds_method_data_init
  37 *
  38 * PARAMETERS:  walk_state          - Current walk state object
  39 *
  40 * RETURN:      Status
  41 *
  42 * DESCRIPTION: Initialize the data structures that hold the method's arguments
  43 *              and locals. The data struct is an array of namespace nodes for
  44 *              each - this allows ref_of and de_ref_of to work properly for these
  45 *              special data types.
  46 *
  47 * NOTES:       walk_state fields are initialized to zero by the
  48 *              ACPI_ALLOCATE_ZEROED().
  49 *
  50 *              A pseudo-Namespace Node is assigned to each argument and local
  51 *              so that ref_of() can return a pointer to the Node.
  52 *
  53 ******************************************************************************/
  54
  55void acpi_ds_method_data_init(struct acpi_walk_state *walk_state)
  56{
  57        u32 i;
  58
  59        ACPI_FUNCTION_TRACE(ds_method_data_init);
  60
  61        /* Init the method arguments */
  62
  63        for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
  64                ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
  65                                   NAMEOF_ARG_NTE);
  66
  67                walk_state->arguments[i].name.integer |= (i << 24);
  68                walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
  69                walk_state->arguments[i].type = ACPI_TYPE_ANY;
  70                walk_state->arguments[i].flags = ANOBJ_METHOD_ARG;
  71        }
  72
  73        /* Init the method locals */
  74
  75        for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
  76                ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name,
  77                                   NAMEOF_LOCAL_NTE);
  78
  79                walk_state->local_variables[i].name.integer |= (i << 24);
  80                walk_state->local_variables[i].descriptor_type =
  81                    ACPI_DESC_TYPE_NAMED;
  82                walk_state->local_variables[i].type = ACPI_TYPE_ANY;
  83                walk_state->local_variables[i].flags = ANOBJ_METHOD_LOCAL;
  84        }
  85
  86        return_VOID;
  87}
  88
  89/*******************************************************************************
  90 *
  91 * FUNCTION:    acpi_ds_method_data_delete_all
  92 *
  93 * PARAMETERS:  walk_state          - Current walk state object
  94 *
  95 * RETURN:      None
  96 *
  97 * DESCRIPTION: Delete method locals and arguments. Arguments are only
  98 *              deleted if this method was called from another method.
  99 *
 100 ******************************************************************************/
 101
 102void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state)
 103{
 104        u32 index;
 105
 106        ACPI_FUNCTION_TRACE(ds_method_data_delete_all);
 107
 108        /* Detach the locals */
 109
 110        for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
 111                if (walk_state->local_variables[index].object) {
 112                        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%u=%p\n",
 113                                          index,
 114                                          walk_state->local_variables[index].
 115                                          object));
 116
 117                        /* Detach object (if present) and remove a reference */
 118
 119                        acpi_ns_detach_object(&walk_state->
 120                                              local_variables[index]);
 121                }
 122        }
 123
 124        /* Detach the arguments */
 125
 126        for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
 127                if (walk_state->arguments[index].object) {
 128                        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%u=%p\n",
 129                                          index,
 130                                          walk_state->arguments[index].object));
 131
 132                        /* Detach object (if present) and remove a reference */
 133
 134                        acpi_ns_detach_object(&walk_state->arguments[index]);
 135                }
 136        }
 137
 138        return_VOID;
 139}
 140
 141/*******************************************************************************
 142 *
 143 * FUNCTION:    acpi_ds_method_data_init_args
 144 *
 145 * PARAMETERS:  *params         - Pointer to a parameter list for the method
 146 *              max_param_count - The arg count for this method
 147 *              walk_state      - Current walk state object
 148 *
 149 * RETURN:      Status
 150 *
 151 * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
 152 *              of ACPI operand objects, either null terminated or whose length
 153 *              is defined by max_param_count.
 154 *
 155 ******************************************************************************/
 156
 157acpi_status
 158acpi_ds_method_data_init_args(union acpi_operand_object **params,
 159                              u32 max_param_count,
 160                              struct acpi_walk_state *walk_state)
 161{
 162        acpi_status status;
 163        u32 index = 0;
 164
 165        ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params);
 166
 167        if (!params) {
 168                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 169                                  "No parameter list passed to method\n"));
 170                return_ACPI_STATUS(AE_OK);
 171        }
 172
 173        /* Copy passed parameters into the new method stack frame */
 174
 175        while ((index < ACPI_METHOD_NUM_ARGS) &&
 176               (index < max_param_count) && params[index]) {
 177                /*
 178                 * A valid parameter.
 179                 * Store the argument in the method/walk descriptor.
 180                 * Do not copy the arg in order to implement call by reference
 181                 */
 182                status =
 183                    acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
 184                                                  params[index], walk_state);
 185                if (ACPI_FAILURE(status)) {
 186                        return_ACPI_STATUS(status);
 187                }
 188
 189                index++;
 190        }
 191
 192        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%u args passed to method\n", index));
 193        return_ACPI_STATUS(AE_OK);
 194}
 195
 196/*******************************************************************************
 197 *
 198 * FUNCTION:    acpi_ds_method_data_get_node
 199 *
 200 * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
 201 *                                    ACPI_REFCLASS_ARG
 202 *              index               - Which Local or Arg whose type to get
 203 *              walk_state          - Current walk state object
 204 *              node                - Where the node is returned.
 205 *
 206 * RETURN:      Status and node
 207 *
 208 * DESCRIPTION: Get the Node associated with a local or arg.
 209 *
 210 ******************************************************************************/
 211
 212acpi_status
 213acpi_ds_method_data_get_node(u8 type,
 214                             u32 index,
 215                             struct acpi_walk_state *walk_state,
 216                             struct acpi_namespace_node **node)
 217{
 218        ACPI_FUNCTION_TRACE(ds_method_data_get_node);
 219
 220        /*
 221         * Method Locals and Arguments are supported
 222         */
 223        switch (type) {
 224        case ACPI_REFCLASS_LOCAL:
 225
 226                if (index > ACPI_METHOD_MAX_LOCAL) {
 227                        ACPI_ERROR((AE_INFO,
 228                                    "Local index %u is invalid (max %u)",
 229                                    index, ACPI_METHOD_MAX_LOCAL));
 230                        return_ACPI_STATUS(AE_AML_INVALID_INDEX);
 231                }
 232
 233                /* Return a pointer to the pseudo-node */
 234
 235                *node = &walk_state->local_variables[index];
 236                break;
 237
 238        case ACPI_REFCLASS_ARG:
 239
 240                if (index > ACPI_METHOD_MAX_ARG) {
 241                        ACPI_ERROR((AE_INFO,
 242                                    "Arg index %u is invalid (max %u)",
 243                                    index, ACPI_METHOD_MAX_ARG));
 244                        return_ACPI_STATUS(AE_AML_INVALID_INDEX);
 245                }
 246
 247                /* Return a pointer to the pseudo-node */
 248
 249                *node = &walk_state->arguments[index];
 250                break;
 251
 252        default:
 253
 254                ACPI_ERROR((AE_INFO, "Type %u is invalid", type));
 255                return_ACPI_STATUS(AE_TYPE);
 256        }
 257
 258        return_ACPI_STATUS(AE_OK);
 259}
 260
 261/*******************************************************************************
 262 *
 263 * FUNCTION:    acpi_ds_method_data_set_value
 264 *
 265 * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
 266 *                                    ACPI_REFCLASS_ARG
 267 *              index               - Which Local or Arg to get
 268 *              object              - Object to be inserted into the stack entry
 269 *              walk_state          - Current walk state object
 270 *
 271 * RETURN:      Status
 272 *
 273 * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
 274 *              Note: There is no "implicit conversion" for locals.
 275 *
 276 ******************************************************************************/
 277
 278static acpi_status
 279acpi_ds_method_data_set_value(u8 type,
 280                              u32 index,
 281                              union acpi_operand_object *object,
 282                              struct acpi_walk_state *walk_state)
 283{
 284        acpi_status status;
 285        struct acpi_namespace_node *node;
 286
 287        ACPI_FUNCTION_TRACE(ds_method_data_set_value);
 288
 289        ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 290                          "NewObj %p Type %2.2X, Refs=%u [%s]\n", object,
 291                          type, object->common.reference_count,
 292                          acpi_ut_get_type_name(object->common.type)));
 293
 294        /* Get the namespace node for the arg/local */
 295
 296        status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
 297        if (ACPI_FAILURE(status)) {
 298                return_ACPI_STATUS(status);
 299        }
 300
 301        /*
 302         * Increment ref count so object can't be deleted while installed.
 303         * NOTE: We do not copy the object in order to preserve the call by
 304         * reference semantics of ACPI Control Method invocation.
 305         * (See ACPI Specification 2.0C)
 306         */
 307        acpi_ut_add_reference(object);
 308
 309        /* Install the object */
 310
 311        node->object = object;
 312        return_ACPI_STATUS(status);
 313}
 314
 315/*******************************************************************************
 316 *
 317 * FUNCTION:    acpi_ds_method_data_get_value
 318 *
 319 * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
 320 *                                    ACPI_REFCLASS_ARG
 321 *              index               - Which localVar or argument to get
 322 *              walk_state          - Current walk state object
 323 *              dest_desc           - Where Arg or Local value is returned
 324 *
 325 * RETURN:      Status
 326 *
 327 * DESCRIPTION: Retrieve value of selected Arg or Local for this method
 328 *              Used only in acpi_ex_resolve_to_value().
 329 *
 330 ******************************************************************************/
 331
 332acpi_status
 333acpi_ds_method_data_get_value(u8 type,
 334                              u32 index,
 335                              struct acpi_walk_state *walk_state,
 336                              union acpi_operand_object **dest_desc)
 337{
 338        acpi_status status;
 339        struct acpi_namespace_node *node;
 340        union acpi_operand_object *object;
 341
 342        ACPI_FUNCTION_TRACE(ds_method_data_get_value);
 343
 344        /* Validate the object descriptor */
 345
 346        if (!dest_desc) {
 347                ACPI_ERROR((AE_INFO, "Null object descriptor pointer"));
 348                return_ACPI_STATUS(AE_BAD_PARAMETER);
 349        }
 350
 351        /* Get the namespace node for the arg/local */
 352
 353        status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
 354        if (ACPI_FAILURE(status)) {
 355                return_ACPI_STATUS(status);
 356        }
 357
 358        /* Get the object from the node */
 359
 360        object = node->object;
 361
 362        /* Examine the returned object, it must be valid. */
 363
 364        if (!object) {
 365                /*
 366                 * Index points to uninitialized object.
 367                 * This means that either 1) The expected argument was
 368                 * not passed to the method, or 2) A local variable
 369                 * was referenced by the method (via the ASL)
 370                 * before it was initialized. Either case is an error.
 371                 */
 372
 373                /* If slack enabled, init the local_x/arg_x to an Integer of value zero */
 374
 375                if (acpi_gbl_enable_interpreter_slack) {
 376                        object = acpi_ut_create_integer_object((u64) 0);
 377                        if (!object) {
 378                                return_ACPI_STATUS(AE_NO_MEMORY);
 379                        }
 380
 381                        node->object = object;
 382                }
 383
 384                /* Otherwise, return the error */
 385
 386                else
 387                        switch (type) {
 388                        case ACPI_REFCLASS_ARG:
 389
 390                                ACPI_ERROR((AE_INFO,
 391                                            "Uninitialized Arg[%u] at node %p",
 392                                            index, node));
 393
 394                                return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG);
 395
 396                        case ACPI_REFCLASS_LOCAL:
 397                                /*
 398                                 * No error message for this case, will be trapped again later to
 399                                 * detect and ignore cases of Store(local_x,local_x)
 400                                 */
 401                                return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
 402
 403                        default:
 404
 405                                ACPI_ERROR((AE_INFO,
 406                                            "Not a Arg/Local opcode: 0x%X",
 407                                            type));
 408                                return_ACPI_STATUS(AE_AML_INTERNAL);
 409                        }
 410        }
 411
 412        /*
 413         * The Index points to an initialized and valid object.
 414         * Return an additional reference to the object
 415         */
 416        *dest_desc = object;
 417        acpi_ut_add_reference(object);
 418
 419        return_ACPI_STATUS(AE_OK);
 420}
 421
 422/*******************************************************************************
 423 *
 424 * FUNCTION:    acpi_ds_method_data_delete_value
 425 *
 426 * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
 427 *                                    ACPI_REFCLASS_ARG
 428 *              index               - Which localVar or argument to delete
 429 *              walk_state          - Current walk state object
 430 *
 431 * RETURN:      None
 432 *
 433 * DESCRIPTION: Delete the entry at Opcode:Index. Inserts
 434 *              a null into the stack slot after the object is deleted.
 435 *
 436 ******************************************************************************/
 437
 438static void
 439acpi_ds_method_data_delete_value(u8 type,
 440                                 u32 index, struct acpi_walk_state *walk_state)
 441{
 442        acpi_status status;
 443        struct acpi_namespace_node *node;
 444        union acpi_operand_object *object;
 445
 446        ACPI_FUNCTION_TRACE(ds_method_data_delete_value);
 447
 448        /* Get the namespace node for the arg/local */
 449
 450        status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
 451        if (ACPI_FAILURE(status)) {
 452                return_VOID;
 453        }
 454
 455        /* Get the associated object */
 456
 457        object = acpi_ns_get_attached_object(node);
 458
 459        /*
 460         * Undefine the Arg or Local by setting its descriptor
 461         * pointer to NULL. Locals/Args can contain both
 462         * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
 463         */
 464        node->object = NULL;
 465
 466        if ((object) &&
 467            (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) {
 468                /*
 469                 * There is a valid object.
 470                 * Decrement the reference count by one to balance the
 471                 * increment when the object was stored.
 472                 */
 473                acpi_ut_remove_reference(object);
 474        }
 475
 476        return_VOID;
 477}
 478
 479/*******************************************************************************
 480 *
 481 * FUNCTION:    acpi_ds_store_object_to_local
 482 *
 483 * PARAMETERS:  type                - Either ACPI_REFCLASS_LOCAL or
 484 *                                    ACPI_REFCLASS_ARG
 485 *              index               - Which Local or Arg to set
 486 *              obj_desc            - Value to be stored
 487 *              walk_state          - Current walk state
 488 *
 489 * RETURN:      Status
 490 *
 491 * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
 492 *              as the new value for the Arg or Local and the reference count
 493 *              for obj_desc is incremented.
 494 *
 495 ******************************************************************************/
 496
 497acpi_status
 498acpi_ds_store_object_to_local(u8 type,
 499                              u32 index,
 500                              union acpi_operand_object *obj_desc,
 501                              struct acpi_walk_state *walk_state)
 502{
 503        acpi_status status;
 504        struct acpi_namespace_node *node;
 505        union acpi_operand_object *current_obj_desc;
 506        union acpi_operand_object *new_obj_desc;
 507
 508        ACPI_FUNCTION_TRACE(ds_store_object_to_local);
 509        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%u Obj=%p\n",
 510                          type, index, obj_desc));
 511
 512        /* Parameter validation */
 513
 514        if (!obj_desc) {
 515                return_ACPI_STATUS(AE_BAD_PARAMETER);
 516        }
 517
 518        /* Get the namespace node for the arg/local */
 519
 520        status = acpi_ds_method_data_get_node(type, index, walk_state, &node);
 521        if (ACPI_FAILURE(status)) {
 522                return_ACPI_STATUS(status);
 523        }
 524
 525        current_obj_desc = acpi_ns_get_attached_object(node);
 526        if (current_obj_desc == obj_desc) {
 527                ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n",
 528                                  obj_desc));
 529                return_ACPI_STATUS(status);
 530        }
 531
 532        /*
 533         * If the reference count on the object is more than one, we must
 534         * take a copy of the object before we store. A reference count
 535         * of exactly 1 means that the object was just created during the
 536         * evaluation of an expression, and we can safely use it since it
 537         * is not used anywhere else.
 538         */
 539        new_obj_desc = obj_desc;
 540        if (obj_desc->common.reference_count > 1) {
 541                status =
 542                    acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc,
 543                                                    walk_state);
 544                if (ACPI_FAILURE(status)) {
 545                        return_ACPI_STATUS(status);
 546                }
 547        }
 548
 549        /*
 550         * If there is an object already in this slot, we either
 551         * have to delete it, or if this is an argument and there
 552         * is an object reference stored there, we have to do
 553         * an indirect store!
 554         */
 555        if (current_obj_desc) {
 556                /*
 557                 * Check for an indirect store if an argument
 558                 * contains an object reference (stored as an Node).
 559                 * We don't allow this automatic dereferencing for
 560                 * locals, since a store to a local should overwrite
 561                 * anything there, including an object reference.
 562                 *
 563                 * If both Arg0 and Local0 contain ref_of (Local4):
 564                 *
 565                 * Store (1, Arg0)             - Causes indirect store to local4
 566                 * Store (1, Local0)           - Stores 1 in local0, overwriting
 567                 *                                  the reference to local4
 568                 * Store (1, de_refof (Local0)) - Causes indirect store to local4
 569                 *
 570                 * Weird, but true.
 571                 */
 572                if (type == ACPI_REFCLASS_ARG) {
 573                        /*
 574                         * If we have a valid reference object that came from ref_of(),
 575                         * do the indirect store
 576                         */
 577                        if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
 578                             ACPI_DESC_TYPE_OPERAND) &&
 579                            (current_obj_desc->common.type ==
 580                             ACPI_TYPE_LOCAL_REFERENCE) &&
 581                            (current_obj_desc->reference.class ==
 582                             ACPI_REFCLASS_REFOF)) {
 583                                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 584                                                  "Arg (%p) is an ObjRef(Node), storing in node %p\n",
 585                                                  new_obj_desc,
 586                                                  current_obj_desc));
 587
 588                                /*
 589                                 * Store this object to the Node (perform the indirect store)
 590                                 * NOTE: No implicit conversion is performed, as per the ACPI
 591                                 * specification rules on storing to Locals/Args.
 592                                 */
 593                                status =
 594                                    acpi_ex_store_object_to_node(new_obj_desc,
 595                                                                 current_obj_desc->
 596                                                                 reference.
 597                                                                 object,
 598                                                                 walk_state,
 599                                                                 ACPI_NO_IMPLICIT_CONVERSION);
 600
 601                                /* Remove local reference if we copied the object above */
 602
 603                                if (new_obj_desc != obj_desc) {
 604                                        acpi_ut_remove_reference(new_obj_desc);
 605                                }
 606
 607                                return_ACPI_STATUS(status);
 608                        }
 609                }
 610
 611                /* Delete the existing object before storing the new one */
 612
 613                acpi_ds_method_data_delete_value(type, index, walk_state);
 614        }
 615
 616        /*
 617         * Install the Obj descriptor (*new_obj_desc) into
 618         * the descriptor for the Arg or Local.
 619         * (increments the object reference count by one)
 620         */
 621        status =
 622            acpi_ds_method_data_set_value(type, index, new_obj_desc,
 623                                          walk_state);
 624
 625        /* Remove local reference if we copied the object above */
 626
 627        if (new_obj_desc != obj_desc) {
 628                acpi_ut_remove_reference(new_obj_desc);
 629        }
 630
 631        return_ACPI_STATUS(status);
 632}
 633
 634#ifdef ACPI_OBSOLETE_FUNCTIONS
 635/*******************************************************************************
 636 *
 637 * FUNCTION:    acpi_ds_method_data_get_type
 638 *
 639 * PARAMETERS:  opcode              - Either AML_FIRST LOCAL_OP or
 640 *                                    AML_FIRST_ARG_OP
 641 *              index               - Which Local or Arg whose type to get
 642 *              walk_state          - Current walk state object
 643 *
 644 * RETURN:      Data type of current value of the selected Arg or Local
 645 *
 646 * DESCRIPTION: Get the type of the object stored in the Local or Arg
 647 *
 648 ******************************************************************************/
 649
 650acpi_object_type
 651acpi_ds_method_data_get_type(u16 opcode,
 652                             u32 index, struct acpi_walk_state *walk_state)
 653{
 654        acpi_status status;
 655        struct acpi_namespace_node *node;
 656        union acpi_operand_object *object;
 657
 658        ACPI_FUNCTION_TRACE(ds_method_data_get_type);
 659
 660        /* Get the namespace node for the arg/local */
 661
 662        status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node);
 663        if (ACPI_FAILURE(status)) {
 664                return_VALUE((ACPI_TYPE_NOT_FOUND));
 665        }
 666
 667        /* Get the object */
 668
 669        object = acpi_ns_get_attached_object(node);
 670        if (!object) {
 671
 672                /* Uninitialized local/arg, return TYPE_ANY */
 673
 674                return_VALUE(ACPI_TYPE_ANY);
 675        }
 676
 677        /* Get the object type */
 678
 679        return_VALUE(object->type);
 680}
 681#endif
 682