root/drivers/acpi/acpica/exresolv.c

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

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ex_resolve_object_to_value
  3. acpi_ex_resolve_multiple

   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 - 2019, 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
  18 ACPI_MODULE_NAME("exresolv")
  19 
  20 /* Local prototypes */
  21 static acpi_status
  22 acpi_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 
  40 acpi_status
  41 acpi_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 
 102 static acpi_status
 103 acpi_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 
 301 acpi_status
 302 acpi_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 
 509 exit:
 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 }

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