linux/drivers/acpi/acpica/dsobject.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: dsobject - Dispatcher object management routines
   5 *
   6 * Copyright (C) 2000 - 2020, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "acparser.h"
  13#include "amlcode.h"
  14#include "acdispat.h"
  15#include "acnamesp.h"
  16#include "acinterp.h"
  17
  18#define _COMPONENT          ACPI_DISPATCHER
  19ACPI_MODULE_NAME("dsobject")
  20
  21/*******************************************************************************
  22 *
  23 * FUNCTION:    acpi_ds_build_internal_object
  24 *
  25 * PARAMETERS:  walk_state      - Current walk state
  26 *              op              - Parser object to be translated
  27 *              obj_desc_ptr    - Where the ACPI internal object is returned
  28 *
  29 * RETURN:      Status
  30 *
  31 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
  32 *              Simple objects are any objects other than a package object!
  33 *
  34 ******************************************************************************/
  35acpi_status
  36acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
  37                              union acpi_parse_object *op,
  38                              union acpi_operand_object **obj_desc_ptr)
  39{
  40        union acpi_operand_object *obj_desc;
  41        acpi_status status;
  42
  43        ACPI_FUNCTION_TRACE(ds_build_internal_object);
  44
  45        *obj_desc_ptr = NULL;
  46        if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
  47                /*
  48                 * This is a named object reference. If this name was
  49                 * previously looked up in the namespace, it was stored in
  50                 * this op. Otherwise, go ahead and look it up now
  51                 */
  52                if (!op->common.node) {
  53
  54                        /* Check if we are resolving a named reference within a package */
  55
  56                        if ((op->common.parent->common.aml_opcode ==
  57                             AML_PACKAGE_OP)
  58                            || (op->common.parent->common.aml_opcode ==
  59                                AML_VARIABLE_PACKAGE_OP)) {
  60                                /*
  61                                 * We won't resolve package elements here, we will do this
  62                                 * after all ACPI tables are loaded into the namespace. This
  63                                 * behavior supports both forward references to named objects
  64                                 * and external references to objects in other tables.
  65                                 */
  66                                goto create_new_object;
  67                        } else {
  68                                status = acpi_ns_lookup(walk_state->scope_info,
  69                                                        op->common.value.string,
  70                                                        ACPI_TYPE_ANY,
  71                                                        ACPI_IMODE_EXECUTE,
  72                                                        ACPI_NS_SEARCH_PARENT |
  73                                                        ACPI_NS_DONT_OPEN_SCOPE,
  74                                                        NULL,
  75                                                        ACPI_CAST_INDIRECT_PTR
  76                                                        (struct
  77                                                         acpi_namespace_node,
  78                                                         &(op->common.node)));
  79                                if (ACPI_FAILURE(status)) {
  80                                        ACPI_ERROR_NAMESPACE(walk_state->
  81                                                             scope_info,
  82                                                             op->common.value.
  83                                                             string, status);
  84                                        return_ACPI_STATUS(status);
  85                                }
  86                        }
  87                }
  88        }
  89
  90create_new_object:
  91
  92        /* Create and init a new internal ACPI object */
  93
  94        obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
  95                                                   (op->common.aml_opcode))->
  96                                                  object_type);
  97        if (!obj_desc) {
  98                return_ACPI_STATUS(AE_NO_MEMORY);
  99        }
 100
 101        status =
 102            acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
 103                                        &obj_desc);
 104        if (ACPI_FAILURE(status)) {
 105                acpi_ut_remove_reference(obj_desc);
 106                return_ACPI_STATUS(status);
 107        }
 108
 109        /*
 110         * Handling for unresolved package reference elements.
 111         * These are elements that are namepaths.
 112         */
 113        if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
 114            (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
 115                obj_desc->reference.resolved = TRUE;
 116
 117                if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
 118                    !obj_desc->reference.node) {
 119                        /*
 120                         * Name was unresolved above.
 121                         * Get the prefix node for later lookup
 122                         */
 123                        obj_desc->reference.node =
 124                            walk_state->scope_info->scope.node;
 125                        obj_desc->reference.aml = op->common.aml;
 126                        obj_desc->reference.resolved = FALSE;
 127                }
 128        }
 129
 130        *obj_desc_ptr = obj_desc;
 131        return_ACPI_STATUS(status);
 132}
 133
 134/*******************************************************************************
 135 *
 136 * FUNCTION:    acpi_ds_build_internal_buffer_obj
 137 *
 138 * PARAMETERS:  walk_state      - Current walk state
 139 *              op              - Parser object to be translated
 140 *              buffer_length   - Length of the buffer
 141 *              obj_desc_ptr    - Where the ACPI internal object is returned
 142 *
 143 * RETURN:      Status
 144 *
 145 * DESCRIPTION: Translate a parser Op package object to the equivalent
 146 *              namespace object
 147 *
 148 ******************************************************************************/
 149
 150acpi_status
 151acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
 152                                  union acpi_parse_object *op,
 153                                  u32 buffer_length,
 154                                  union acpi_operand_object **obj_desc_ptr)
 155{
 156        union acpi_parse_object *arg;
 157        union acpi_operand_object *obj_desc;
 158        union acpi_parse_object *byte_list;
 159        u32 byte_list_length = 0;
 160
 161        ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj);
 162
 163        /*
 164         * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
 165         * The buffer object already exists (from the NS node), otherwise it must
 166         * be created.
 167         */
 168        obj_desc = *obj_desc_ptr;
 169        if (!obj_desc) {
 170
 171                /* Create a new buffer object */
 172
 173                obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
 174                *obj_desc_ptr = obj_desc;
 175                if (!obj_desc) {
 176                        return_ACPI_STATUS(AE_NO_MEMORY);
 177                }
 178        }
 179
 180        /*
 181         * Second arg is the buffer data (optional) byte_list can be either
 182         * individual bytes or a string initializer. In either case, a
 183         * byte_list appears in the AML.
 184         */
 185        arg = op->common.value.arg;     /* skip first arg */
 186
 187        byte_list = arg->named.next;
 188        if (byte_list) {
 189                if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
 190                        ACPI_ERROR((AE_INFO,
 191                                    "Expecting bytelist, found AML opcode 0x%X in op %p",
 192                                    byte_list->common.aml_opcode, byte_list));
 193
 194                        acpi_ut_remove_reference(obj_desc);
 195                        return (AE_TYPE);
 196                }
 197
 198                byte_list_length = (u32) byte_list->common.value.integer;
 199        }
 200
 201        /*
 202         * The buffer length (number of bytes) will be the larger of:
 203         * 1) The specified buffer length and
 204         * 2) The length of the initializer byte list
 205         */
 206        obj_desc->buffer.length = buffer_length;
 207        if (byte_list_length > buffer_length) {
 208                obj_desc->buffer.length = byte_list_length;
 209        }
 210
 211        /* Allocate the buffer */
 212
 213        if (obj_desc->buffer.length == 0) {
 214                obj_desc->buffer.pointer = NULL;
 215                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 216                                  "Buffer defined with zero length in AML, creating\n"));
 217        } else {
 218                obj_desc->buffer.pointer =
 219                    ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length);
 220                if (!obj_desc->buffer.pointer) {
 221                        acpi_ut_delete_object_desc(obj_desc);
 222                        return_ACPI_STATUS(AE_NO_MEMORY);
 223                }
 224
 225                /* Initialize buffer from the byte_list (if present) */
 226
 227                if (byte_list) {
 228                        memcpy(obj_desc->buffer.pointer, byte_list->named.data,
 229                               byte_list_length);
 230                }
 231        }
 232
 233        obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
 234        op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
 235        return_ACPI_STATUS(AE_OK);
 236}
 237
 238/*******************************************************************************
 239 *
 240 * FUNCTION:    acpi_ds_create_node
 241 *
 242 * PARAMETERS:  walk_state      - Current walk state
 243 *              node            - NS Node to be initialized
 244 *              op              - Parser object to be translated
 245 *
 246 * RETURN:      Status
 247 *
 248 * DESCRIPTION: Create the object to be associated with a namespace node
 249 *
 250 ******************************************************************************/
 251
 252acpi_status
 253acpi_ds_create_node(struct acpi_walk_state *walk_state,
 254                    struct acpi_namespace_node *node,
 255                    union acpi_parse_object *op)
 256{
 257        acpi_status status;
 258        union acpi_operand_object *obj_desc;
 259
 260        ACPI_FUNCTION_TRACE_PTR(ds_create_node, op);
 261
 262        /*
 263         * Because of the execution pass through the non-control-method
 264         * parts of the table, we can arrive here twice. Only init
 265         * the named object node the first time through
 266         */
 267        if (acpi_ns_get_attached_object(node)) {
 268                return_ACPI_STATUS(AE_OK);
 269        }
 270
 271        if (!op->common.value.arg) {
 272
 273                /* No arguments, there is nothing to do */
 274
 275                return_ACPI_STATUS(AE_OK);
 276        }
 277
 278        /* Build an internal object for the argument(s) */
 279
 280        status =
 281            acpi_ds_build_internal_object(walk_state, op->common.value.arg,
 282                                          &obj_desc);
 283        if (ACPI_FAILURE(status)) {
 284                return_ACPI_STATUS(status);
 285        }
 286
 287        /* Re-type the object according to its argument */
 288
 289        node->type = obj_desc->common.type;
 290
 291        /* Attach obj to node */
 292
 293        status = acpi_ns_attach_object(node, obj_desc, node->type);
 294
 295        /* Remove local reference to the object */
 296
 297        acpi_ut_remove_reference(obj_desc);
 298        return_ACPI_STATUS(status);
 299}
 300
 301/*******************************************************************************
 302 *
 303 * FUNCTION:    acpi_ds_init_object_from_op
 304 *
 305 * PARAMETERS:  walk_state      - Current walk state
 306 *              op              - Parser op used to init the internal object
 307 *              opcode          - AML opcode associated with the object
 308 *              ret_obj_desc    - Namespace object to be initialized
 309 *
 310 * RETURN:      Status
 311 *
 312 * DESCRIPTION: Initialize a namespace object from a parser Op and its
 313 *              associated arguments. The namespace object is a more compact
 314 *              representation of the Op and its arguments.
 315 *
 316 ******************************************************************************/
 317
 318acpi_status
 319acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
 320                            union acpi_parse_object *op,
 321                            u16 opcode,
 322                            union acpi_operand_object **ret_obj_desc)
 323{
 324        const struct acpi_opcode_info *op_info;
 325        union acpi_operand_object *obj_desc;
 326        acpi_status status = AE_OK;
 327
 328        ACPI_FUNCTION_TRACE(ds_init_object_from_op);
 329
 330        obj_desc = *ret_obj_desc;
 331        op_info = acpi_ps_get_opcode_info(opcode);
 332        if (op_info->class == AML_CLASS_UNKNOWN) {
 333
 334                /* Unknown opcode */
 335
 336                return_ACPI_STATUS(AE_TYPE);
 337        }
 338
 339        /* Perform per-object initialization */
 340
 341        switch (obj_desc->common.type) {
 342        case ACPI_TYPE_BUFFER:
 343                /*
 344                 * Defer evaluation of Buffer term_arg operand
 345                 */
 346                obj_desc->buffer.node =
 347                    ACPI_CAST_PTR(struct acpi_namespace_node,
 348                                  walk_state->operands[0]);
 349                obj_desc->buffer.aml_start = op->named.data;
 350                obj_desc->buffer.aml_length = op->named.length;
 351                break;
 352
 353        case ACPI_TYPE_PACKAGE:
 354                /*
 355                 * Defer evaluation of Package term_arg operand and all
 356                 * package elements. (01/2017): We defer the element
 357                 * resolution to allow forward references from the package
 358                 * in order to provide compatibility with other ACPI
 359                 * implementations.
 360                 */
 361                obj_desc->package.node =
 362                    ACPI_CAST_PTR(struct acpi_namespace_node,
 363                                  walk_state->operands[0]);
 364
 365                if (!op->named.data) {
 366                        return_ACPI_STATUS(AE_OK);
 367                }
 368
 369                obj_desc->package.aml_start = op->named.data;
 370                obj_desc->package.aml_length = op->named.length;
 371                break;
 372
 373        case ACPI_TYPE_INTEGER:
 374
 375                switch (op_info->type) {
 376                case AML_TYPE_CONSTANT:
 377                        /*
 378                         * Resolve AML Constants here - AND ONLY HERE!
 379                         * All constants are integers.
 380                         * We mark the integer with a flag that indicates that it started
 381                         * life as a constant -- so that stores to constants will perform
 382                         * as expected (noop). zero_op is used as a placeholder for optional
 383                         * target operands.
 384                         */
 385                        obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
 386
 387                        switch (opcode) {
 388                        case AML_ZERO_OP:
 389
 390                                obj_desc->integer.value = 0;
 391                                break;
 392
 393                        case AML_ONE_OP:
 394
 395                                obj_desc->integer.value = 1;
 396                                break;
 397
 398                        case AML_ONES_OP:
 399
 400                                obj_desc->integer.value = ACPI_UINT64_MAX;
 401
 402                                /* Truncate value if we are executing from a 32-bit ACPI table */
 403
 404                                (void)acpi_ex_truncate_for32bit_table(obj_desc);
 405                                break;
 406
 407                        case AML_REVISION_OP:
 408
 409                                obj_desc->integer.value = ACPI_CA_VERSION;
 410                                break;
 411
 412                        default:
 413
 414                                ACPI_ERROR((AE_INFO,
 415                                            "Unknown constant opcode 0x%X",
 416                                            opcode));
 417                                status = AE_AML_OPERAND_TYPE;
 418                                break;
 419                        }
 420                        break;
 421
 422                case AML_TYPE_LITERAL:
 423
 424                        obj_desc->integer.value = op->common.value.integer;
 425
 426                        if (acpi_ex_truncate_for32bit_table(obj_desc)) {
 427
 428                                /* Warn if we found a 64-bit constant in a 32-bit table */
 429
 430                                ACPI_WARNING((AE_INFO,
 431                                              "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
 432                                              ACPI_FORMAT_UINT64(op->common.
 433                                                                 value.integer),
 434                                              (u32)obj_desc->integer.value));
 435                        }
 436                        break;
 437
 438                default:
 439
 440                        ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X",
 441                                    op_info->type));
 442                        status = AE_AML_OPERAND_TYPE;
 443                        break;
 444                }
 445                break;
 446
 447        case ACPI_TYPE_STRING:
 448
 449                obj_desc->string.pointer = op->common.value.string;
 450                obj_desc->string.length = (u32)strlen(op->common.value.string);
 451
 452                /*
 453                 * The string is contained in the ACPI table, don't ever try
 454                 * to delete it
 455                 */
 456                obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
 457                break;
 458
 459        case ACPI_TYPE_METHOD:
 460                break;
 461
 462        case ACPI_TYPE_LOCAL_REFERENCE:
 463
 464                switch (op_info->type) {
 465                case AML_TYPE_LOCAL_VARIABLE:
 466
 467                        /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
 468
 469                        obj_desc->reference.value =
 470                            ((u32)opcode) - AML_FIRST_LOCAL_OP;
 471                        obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
 472
 473                        status =
 474                            acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL,
 475                                                         obj_desc->reference.
 476                                                         value, walk_state,
 477                                                         ACPI_CAST_INDIRECT_PTR
 478                                                         (struct
 479                                                          acpi_namespace_node,
 480                                                          &obj_desc->reference.
 481                                                          object));
 482                        break;
 483
 484                case AML_TYPE_METHOD_ARGUMENT:
 485
 486                        /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
 487
 488                        obj_desc->reference.value =
 489                            ((u32)opcode) - AML_FIRST_ARG_OP;
 490                        obj_desc->reference.class = ACPI_REFCLASS_ARG;
 491
 492                        status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG,
 493                                                              obj_desc->
 494                                                              reference.value,
 495                                                              walk_state,
 496                                                              ACPI_CAST_INDIRECT_PTR
 497                                                              (struct
 498                                                               acpi_namespace_node,
 499                                                               &obj_desc->
 500                                                               reference.
 501                                                               object));
 502                        break;
 503
 504                default:        /* Object name or Debug object */
 505
 506                        switch (op->common.aml_opcode) {
 507                        case AML_INT_NAMEPATH_OP:
 508
 509                                /* Node was saved in Op */
 510
 511                                obj_desc->reference.node = op->common.node;
 512                                obj_desc->reference.class = ACPI_REFCLASS_NAME;
 513                                if (op->common.node) {
 514                                        obj_desc->reference.object =
 515                                            op->common.node->object;
 516                                }
 517                                break;
 518
 519                        case AML_DEBUG_OP:
 520
 521                                obj_desc->reference.class = ACPI_REFCLASS_DEBUG;
 522                                break;
 523
 524                        default:
 525
 526                                ACPI_ERROR((AE_INFO,
 527                                            "Unimplemented reference type for AML opcode: 0x%4.4X",
 528                                            opcode));
 529                                return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 530                        }
 531                        break;
 532                }
 533                break;
 534
 535        default:
 536
 537                ACPI_ERROR((AE_INFO, "Unimplemented data type: 0x%X",
 538                            obj_desc->common.type));
 539
 540                status = AE_AML_OPERAND_TYPE;
 541                break;
 542        }
 543
 544        return_ACPI_STATUS(status);
 545}
 546