root/drivers/acpi/acpica/dsobject.c

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

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ds_build_internal_buffer_obj
  3. acpi_ds_create_node
  4. acpi_ds_init_object_from_op

   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 - 2019, 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
  19 ACPI_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  ******************************************************************************/
  35 acpi_status
  36 acpi_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 
  90 create_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 
 150 acpi_status
 151 acpi_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 
 252 acpi_status
 253 acpi_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 
 318 acpi_status
 319 acpi_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 }

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