linux/drivers/acpi/acpica/exresolv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: exresolv - AML Interpreter object resolution
   5 *
   6 * Copyright (C) 2000 - 2020, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "amlcode.h"
  13#include "acdispat.h"
  14#include "acinterp.h"
  15#include "acnamesp.h"
  16
  17#define _COMPONENT          ACPI_EXECUTER
  18ACPI_MODULE_NAME("exresolv")
  19
  20/* Local prototypes */
  21static acpi_status
  22acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
  23                                struct acpi_walk_state *walk_state);
  24
  25/*******************************************************************************
  26 *
  27 * FUNCTION:    acpi_ex_resolve_to_value
  28 *
  29 * PARAMETERS:  **stack_ptr         - Points to entry on obj_stack, which can
  30 *                                    be either an (union acpi_operand_object *)
  31 *                                    or an acpi_handle.
  32 *              walk_state          - Current method state
  33 *
  34 * RETURN:      Status
  35 *
  36 * DESCRIPTION: Convert Reference objects to values
  37 *
  38 ******************************************************************************/
  39
  40acpi_status
  41acpi_ex_resolve_to_value(union acpi_operand_object **stack_ptr,
  42                         struct acpi_walk_state *walk_state)
  43{
  44        acpi_status status;
  45
  46        ACPI_FUNCTION_TRACE_PTR(ex_resolve_to_value, stack_ptr);
  47
  48        if (!stack_ptr || !*stack_ptr) {
  49                ACPI_ERROR((AE_INFO, "Internal - null pointer"));
  50                return_ACPI_STATUS(AE_AML_NO_OPERAND);
  51        }
  52
  53        /*
  54         * The entity pointed to by the stack_ptr can be either
  55         * 1) A valid union acpi_operand_object, or
  56         * 2) A struct acpi_namespace_node (named_obj)
  57         */
  58        if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
  59                status = acpi_ex_resolve_object_to_value(stack_ptr, walk_state);
  60                if (ACPI_FAILURE(status)) {
  61                        return_ACPI_STATUS(status);
  62                }
  63
  64                if (!*stack_ptr) {
  65                        ACPI_ERROR((AE_INFO, "Internal - null pointer"));
  66                        return_ACPI_STATUS(AE_AML_NO_OPERAND);
  67                }
  68        }
  69
  70        /*
  71         * Object on the stack may have changed if acpi_ex_resolve_object_to_value()
  72         * was called (i.e., we can't use an _else_ here.)
  73         */
  74        if (ACPI_GET_DESCRIPTOR_TYPE(*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
  75                status =
  76                    acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
  77                                                  (struct acpi_namespace_node,
  78                                                   stack_ptr), walk_state);
  79                if (ACPI_FAILURE(status)) {
  80                        return_ACPI_STATUS(status);
  81                }
  82        }
  83
  84        ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
  85        return_ACPI_STATUS(AE_OK);
  86}
  87
  88/*******************************************************************************
  89 *
  90 * FUNCTION:    acpi_ex_resolve_object_to_value
  91 *
  92 * PARAMETERS:  stack_ptr       - Pointer to an internal object
  93 *              walk_state      - Current method state
  94 *
  95 * RETURN:      Status
  96 *
  97 * DESCRIPTION: Retrieve the value from an internal object. The Reference type
  98 *              uses the associated AML opcode to determine the value.
  99 *
 100 ******************************************************************************/
 101
 102static acpi_status
 103acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
 104                                struct acpi_walk_state *walk_state)
 105{
 106        acpi_status status = AE_OK;
 107        union acpi_operand_object *stack_desc;
 108        union acpi_operand_object *obj_desc = NULL;
 109        u8 ref_type;
 110
 111        ACPI_FUNCTION_TRACE(ex_resolve_object_to_value);
 112
 113        stack_desc = *stack_ptr;
 114
 115        /* This is an object of type union acpi_operand_object */
 116
 117        switch (stack_desc->common.type) {
 118        case ACPI_TYPE_LOCAL_REFERENCE:
 119
 120                ref_type = stack_desc->reference.class;
 121
 122                switch (ref_type) {
 123                case ACPI_REFCLASS_LOCAL:
 124                case ACPI_REFCLASS_ARG:
 125                        /*
 126                         * Get the local from the method's state info
 127                         * Note: this increments the local's object reference count
 128                         */
 129                        status = acpi_ds_method_data_get_value(ref_type,
 130                                                               stack_desc->
 131                                                               reference.value,
 132                                                               walk_state,
 133                                                               &obj_desc);
 134                        if (ACPI_FAILURE(status)) {
 135                                return_ACPI_STATUS(status);
 136                        }
 137
 138                        ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 139                                          "[Arg/Local %X] ValueObj is %p\n",
 140                                          stack_desc->reference.value,
 141                                          obj_desc));
 142
 143                        /*
 144                         * Now we can delete the original Reference Object and
 145                         * replace it with the resolved value
 146                         */
 147                        acpi_ut_remove_reference(stack_desc);
 148                        *stack_ptr = obj_desc;
 149                        break;
 150
 151                case ACPI_REFCLASS_INDEX:
 152
 153                        switch (stack_desc->reference.target_type) {
 154                        case ACPI_TYPE_BUFFER_FIELD:
 155
 156                                /* Just return - do not dereference */
 157                                break;
 158
 159                        case ACPI_TYPE_PACKAGE:
 160
 161                                /* If method call or copy_object - do not dereference */
 162
 163                                if ((walk_state->opcode ==
 164                                     AML_INT_METHODCALL_OP)
 165                                    || (walk_state->opcode ==
 166                                        AML_COPY_OBJECT_OP)) {
 167                                        break;
 168                                }
 169
 170                                /* Otherwise, dereference the package_index to a package element */
 171
 172                                obj_desc = *stack_desc->reference.where;
 173                                if (obj_desc) {
 174                                        /*
 175                                         * Valid object descriptor, copy pointer to return value
 176                                         * (i.e., dereference the package index)
 177                                         * Delete the ref object, increment the returned object
 178                                         */
 179                                        acpi_ut_add_reference(obj_desc);
 180                                        *stack_ptr = obj_desc;
 181                                } else {
 182                                        /*
 183                                         * A NULL object descriptor means an uninitialized element of
 184                                         * the package, can't dereference it
 185                                         */
 186                                        ACPI_ERROR((AE_INFO,
 187                                                    "Attempt to dereference an Index to "
 188                                                    "NULL package element Idx=%p",
 189                                                    stack_desc));
 190                                        status = AE_AML_UNINITIALIZED_ELEMENT;
 191                                }
 192                                break;
 193
 194                        default:
 195
 196                                /* Invalid reference object */
 197
 198                                ACPI_ERROR((AE_INFO,
 199                                            "Unknown TargetType 0x%X in Index/Reference object %p",
 200                                            stack_desc->reference.target_type,
 201                                            stack_desc));
 202                                status = AE_AML_INTERNAL;
 203                                break;
 204                        }
 205                        break;
 206
 207                case ACPI_REFCLASS_REFOF:
 208                case ACPI_REFCLASS_DEBUG:
 209                case ACPI_REFCLASS_TABLE:
 210
 211                        /* Just leave the object as-is, do not dereference */
 212
 213                        break;
 214
 215                case ACPI_REFCLASS_NAME:        /* Reference to a named object */
 216
 217                        /* Dereference the name */
 218
 219                        if ((stack_desc->reference.node->type ==
 220                             ACPI_TYPE_DEVICE)
 221                            || (stack_desc->reference.node->type ==
 222                                ACPI_TYPE_THERMAL)) {
 223
 224                                /* These node types do not have 'real' subobjects */
 225
 226                                *stack_ptr = (void *)stack_desc->reference.node;
 227                        } else {
 228                                /* Get the object pointed to by the namespace node */
 229
 230                                *stack_ptr =
 231                                    (stack_desc->reference.node)->object;
 232                                acpi_ut_add_reference(*stack_ptr);
 233                        }
 234
 235                        acpi_ut_remove_reference(stack_desc);
 236                        break;
 237
 238                default:
 239
 240                        ACPI_ERROR((AE_INFO,
 241                                    "Unknown Reference type 0x%X in %p",
 242                                    ref_type, stack_desc));
 243                        status = AE_AML_INTERNAL;
 244                        break;
 245                }
 246                break;
 247
 248        case ACPI_TYPE_BUFFER:
 249
 250                status = acpi_ds_get_buffer_arguments(stack_desc);
 251                break;
 252
 253        case ACPI_TYPE_PACKAGE:
 254
 255                status = acpi_ds_get_package_arguments(stack_desc);
 256                break;
 257
 258        case ACPI_TYPE_BUFFER_FIELD:
 259        case ACPI_TYPE_LOCAL_REGION_FIELD:
 260        case ACPI_TYPE_LOCAL_BANK_FIELD:
 261        case ACPI_TYPE_LOCAL_INDEX_FIELD:
 262
 263                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 264                                  "FieldRead SourceDesc=%p Type=%X\n",
 265                                  stack_desc, stack_desc->common.type));
 266
 267                status =
 268                    acpi_ex_read_data_from_field(walk_state, stack_desc,
 269                                                 &obj_desc);
 270
 271                /* Remove a reference to the original operand, then override */
 272
 273                acpi_ut_remove_reference(*stack_ptr);
 274                *stack_ptr = (void *)obj_desc;
 275                break;
 276
 277        default:
 278
 279                break;
 280        }
 281
 282        return_ACPI_STATUS(status);
 283}
 284
 285/*******************************************************************************
 286 *
 287 * FUNCTION:    acpi_ex_resolve_multiple
 288 *
 289 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
 290 *              operand             - Starting point for resolution
 291 *              return_type         - Where the object type is returned
 292 *              return_desc         - Where the resolved object is returned
 293 *
 294 * RETURN:      Status
 295 *
 296 * DESCRIPTION: Return the base object and type. Traverse a reference list if
 297 *              necessary to get to the base object.
 298 *
 299 ******************************************************************************/
 300
 301acpi_status
 302acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state,
 303                         union acpi_operand_object *operand,
 304                         acpi_object_type *return_type,
 305                         union acpi_operand_object **return_desc)
 306{
 307        union acpi_operand_object *obj_desc = ACPI_CAST_PTR(void, operand);
 308        struct acpi_namespace_node *node =
 309            ACPI_CAST_PTR(struct acpi_namespace_node, operand);
 310        acpi_object_type type;
 311        acpi_status status;
 312
 313        ACPI_FUNCTION_TRACE(acpi_ex_resolve_multiple);
 314
 315        /* Operand can be either a namespace node or an operand descriptor */
 316
 317        switch (ACPI_GET_DESCRIPTOR_TYPE(obj_desc)) {
 318        case ACPI_DESC_TYPE_OPERAND:
 319
 320                type = obj_desc->common.type;
 321                break;
 322
 323        case ACPI_DESC_TYPE_NAMED:
 324
 325                type = ((struct acpi_namespace_node *)obj_desc)->type;
 326                obj_desc = acpi_ns_get_attached_object(node);
 327
 328                /* If we had an Alias node, use the attached object for type info */
 329
 330                if (type == ACPI_TYPE_LOCAL_ALIAS) {
 331                        type = ((struct acpi_namespace_node *)obj_desc)->type;
 332                        obj_desc = acpi_ns_get_attached_object((struct
 333                                                                acpi_namespace_node
 334                                                                *)obj_desc);
 335                }
 336
 337                switch (type) {
 338                case ACPI_TYPE_DEVICE:
 339                case ACPI_TYPE_THERMAL:
 340
 341                        /* These types have no attached subobject */
 342                        break;
 343
 344                default:
 345
 346                        /* All other types require a subobject */
 347
 348                        if (!obj_desc) {
 349                                ACPI_ERROR((AE_INFO,
 350                                            "[%4.4s] Node is unresolved or uninitialized",
 351                                            acpi_ut_get_node_name(node)));
 352                                return_ACPI_STATUS(AE_AML_UNINITIALIZED_NODE);
 353                        }
 354                        break;
 355                }
 356                break;
 357
 358        default:
 359                return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 360        }
 361
 362        /* If type is anything other than a reference, we are done */
 363
 364        if (type != ACPI_TYPE_LOCAL_REFERENCE) {
 365                goto exit;
 366        }
 367
 368        /*
 369         * For reference objects created via the ref_of, Index, or Load/load_table
 370         * operators, we need to get to the base object (as per the ACPI
 371         * specification of the object_type and size_of operators). This means
 372         * traversing the list of possibly many nested references.
 373         */
 374        while (obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
 375                switch (obj_desc->reference.class) {
 376                case ACPI_REFCLASS_REFOF:
 377                case ACPI_REFCLASS_NAME:
 378
 379                        /* Dereference the reference pointer */
 380
 381                        if (obj_desc->reference.class == ACPI_REFCLASS_REFOF) {
 382                                node = obj_desc->reference.object;
 383                        } else {        /* AML_INT_NAMEPATH_OP */
 384
 385                                node = obj_desc->reference.node;
 386                        }
 387
 388                        /* All "References" point to a NS node */
 389
 390                        if (ACPI_GET_DESCRIPTOR_TYPE(node) !=
 391                            ACPI_DESC_TYPE_NAMED) {
 392                                ACPI_ERROR((AE_INFO,
 393                                            "Not a namespace node %p [%s]",
 394                                            node,
 395                                            acpi_ut_get_descriptor_name(node)));
 396                                return_ACPI_STATUS(AE_AML_INTERNAL);
 397                        }
 398
 399                        /* Get the attached object */
 400
 401                        obj_desc = acpi_ns_get_attached_object(node);
 402                        if (!obj_desc) {
 403
 404                                /* No object, use the NS node type */
 405
 406                                type = acpi_ns_get_type(node);
 407                                goto exit;
 408                        }
 409
 410                        /* Check for circular references */
 411
 412                        if (obj_desc == operand) {
 413                                return_ACPI_STATUS(AE_AML_CIRCULAR_REFERENCE);
 414                        }
 415                        break;
 416
 417                case ACPI_REFCLASS_INDEX:
 418
 419                        /* Get the type of this reference (index into another object) */
 420
 421                        type = obj_desc->reference.target_type;
 422                        if (type != ACPI_TYPE_PACKAGE) {
 423                                goto exit;
 424                        }
 425
 426                        /*
 427                         * The main object is a package, we want to get the type
 428                         * of the individual package element that is referenced by
 429                         * the index.
 430                         *
 431                         * This could of course in turn be another reference object.
 432                         */
 433                        obj_desc = *(obj_desc->reference.where);
 434                        if (!obj_desc) {
 435
 436                                /* NULL package elements are allowed */
 437
 438                                type = 0;       /* Uninitialized */
 439                                goto exit;
 440                        }
 441                        break;
 442
 443                case ACPI_REFCLASS_TABLE:
 444
 445                        type = ACPI_TYPE_DDB_HANDLE;
 446                        goto exit;
 447
 448                case ACPI_REFCLASS_LOCAL:
 449                case ACPI_REFCLASS_ARG:
 450
 451                        if (return_desc) {
 452                                status =
 453                                    acpi_ds_method_data_get_value(obj_desc->
 454                                                                  reference.
 455                                                                  class,
 456                                                                  obj_desc->
 457                                                                  reference.
 458                                                                  value,
 459                                                                  walk_state,
 460                                                                  &obj_desc);
 461                                if (ACPI_FAILURE(status)) {
 462                                        return_ACPI_STATUS(status);
 463                                }
 464                                acpi_ut_remove_reference(obj_desc);
 465                        } else {
 466                                status =
 467                                    acpi_ds_method_data_get_node(obj_desc->
 468                                                                 reference.
 469                                                                 class,
 470                                                                 obj_desc->
 471                                                                 reference.
 472                                                                 value,
 473                                                                 walk_state,
 474                                                                 &node);
 475                                if (ACPI_FAILURE(status)) {
 476                                        return_ACPI_STATUS(status);
 477                                }
 478
 479                                obj_desc = acpi_ns_get_attached_object(node);
 480                                if (!obj_desc) {
 481                                        type = ACPI_TYPE_ANY;
 482                                        goto exit;
 483                                }
 484                        }
 485                        break;
 486
 487                case ACPI_REFCLASS_DEBUG:
 488
 489                        /* The Debug Object is of type "DebugObject" */
 490
 491                        type = ACPI_TYPE_DEBUG_OBJECT;
 492                        goto exit;
 493
 494                default:
 495
 496                        ACPI_ERROR((AE_INFO,
 497                                    "Unknown Reference Class 0x%2.2X",
 498                                    obj_desc->reference.class));
 499                        return_ACPI_STATUS(AE_AML_INTERNAL);
 500                }
 501        }
 502
 503        /*
 504         * Now we are guaranteed to have an object that has not been created
 505         * via the ref_of or Index operators.
 506         */
 507        type = obj_desc->common.type;
 508
 509exit:
 510        /* Convert internal types to external types */
 511
 512        switch (type) {
 513        case ACPI_TYPE_LOCAL_REGION_FIELD:
 514        case ACPI_TYPE_LOCAL_BANK_FIELD:
 515        case ACPI_TYPE_LOCAL_INDEX_FIELD:
 516
 517                type = ACPI_TYPE_FIELD_UNIT;
 518                break;
 519
 520        case ACPI_TYPE_LOCAL_SCOPE:
 521
 522                /* Per ACPI Specification, Scope is untyped */
 523
 524                type = ACPI_TYPE_ANY;
 525                break;
 526
 527        default:
 528
 529                /* No change to Type required */
 530
 531                break;
 532        }
 533
 534        *return_type = type;
 535        if (return_desc) {
 536                *return_desc = obj_desc;
 537        }
 538        return_ACPI_STATUS(AE_OK);
 539}
 540