root/drivers/acpi/acpica/dspkginit.c

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

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ds_init_package_element
  3. acpi_ds_resolve_package_element

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: dspkginit - Completion of deferred package initialization
   5  *
   6  * Copyright (C) 2000 - 2019, Intel Corp.
   7  *
   8  *****************************************************************************/
   9 
  10 #include <acpi/acpi.h>
  11 #include "accommon.h"
  12 #include "acnamesp.h"
  13 #include "amlcode.h"
  14 #include "acdispat.h"
  15 #include "acinterp.h"
  16 #include "acparser.h"
  17 
  18 #define _COMPONENT          ACPI_NAMESPACE
  19 ACPI_MODULE_NAME("dspkginit")
  20 
  21 /* Local prototypes */
  22 static void
  23 acpi_ds_resolve_package_element(union acpi_operand_object **element);
  24 
  25 /*******************************************************************************
  26  *
  27  * FUNCTION:    acpi_ds_build_internal_package_obj
  28  *
  29  * PARAMETERS:  walk_state      - Current walk state
  30  *              op              - Parser object to be translated
  31  *              element_count   - Number of elements in the package - this is
  32  *                                the num_elements argument to Package()
  33  *              obj_desc_ptr    - Where the ACPI internal object is returned
  34  *
  35  * RETURN:      Status
  36  *
  37  * DESCRIPTION: Translate a parser Op package object to the equivalent
  38  *              namespace object
  39  *
  40  * NOTE: The number of elements in the package will be always be the num_elements
  41  * count, regardless of the number of elements in the package list. If
  42  * num_elements is smaller, only that many package list elements are used.
  43  * if num_elements is larger, the Package object is padded out with
  44  * objects of type Uninitialized (as per ACPI spec.)
  45  *
  46  * Even though the ASL compilers do not allow num_elements to be smaller
  47  * than the Package list length (for the fixed length package opcode), some
  48  * BIOS code modifies the AML on the fly to adjust the num_elements, and
  49  * this code compensates for that. This also provides compatibility with
  50  * other AML interpreters.
  51  *
  52  ******************************************************************************/
  53 
  54 acpi_status
  55 acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
  56                                    union acpi_parse_object *op,
  57                                    u32 element_count,
  58                                    union acpi_operand_object **obj_desc_ptr)
  59 {
  60         union acpi_parse_object *arg;
  61         union acpi_parse_object *parent;
  62         union acpi_operand_object *obj_desc = NULL;
  63         acpi_status status = AE_OK;
  64         u8 module_level_code = FALSE;
  65         u16 reference_count;
  66         u32 index;
  67         u32 i;
  68 
  69         ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
  70 
  71         /* Check if we are executing module level code */
  72 
  73         if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) {
  74                 module_level_code = TRUE;
  75         }
  76 
  77         /* Find the parent of a possibly nested package */
  78 
  79         parent = op->common.parent;
  80         while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
  81                (parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
  82                 parent = parent->common.parent;
  83         }
  84 
  85         /*
  86          * If we are evaluating a Named package object of the form:
  87          *      Name (xxxx, Package)
  88          * the package object already exists, otherwise it must be created.
  89          */
  90         obj_desc = *obj_desc_ptr;
  91         if (!obj_desc) {
  92                 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
  93                 *obj_desc_ptr = obj_desc;
  94                 if (!obj_desc) {
  95                         return_ACPI_STATUS(AE_NO_MEMORY);
  96                 }
  97 
  98                 obj_desc->package.node = parent->common.node;
  99         }
 100 
 101         if (obj_desc->package.flags & AOPOBJ_DATA_VALID) {      /* Just in case */
 102                 return_ACPI_STATUS(AE_OK);
 103         }
 104 
 105         /*
 106          * Allocate the element array (array of pointers to the individual
 107          * objects) if necessary. the count is based on the num_elements
 108          * parameter. Add an extra pointer slot so that the list is always
 109          * null terminated.
 110          */
 111         if (!obj_desc->package.elements) {
 112                 obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
 113                                                                    element_count
 114                                                                    +
 115                                                                    1) *
 116                                                                   sizeof(void
 117                                                                          *));
 118 
 119                 if (!obj_desc->package.elements) {
 120                         acpi_ut_delete_object_desc(obj_desc);
 121                         return_ACPI_STATUS(AE_NO_MEMORY);
 122                 }
 123 
 124                 obj_desc->package.count = element_count;
 125         }
 126 
 127         /* First arg is element count. Second arg begins the initializer list */
 128 
 129         arg = op->common.value.arg;
 130         arg = arg->common.next;
 131 
 132         /*
 133          * If we are executing module-level code, we will defer the
 134          * full resolution of the package elements in order to support
 135          * forward references from the elements. This provides
 136          * compatibility with other ACPI implementations.
 137          */
 138         if (module_level_code) {
 139                 obj_desc->package.aml_start = walk_state->aml;
 140                 obj_desc->package.aml_length = 0;
 141 
 142                 ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
 143                                       "%s: Deferring resolution of Package elements\n",
 144                                       ACPI_GET_FUNCTION_NAME));
 145         }
 146 
 147         /*
 148          * Initialize the elements of the package, up to the num_elements count.
 149          * Package is automatically padded with uninitialized (NULL) elements
 150          * if num_elements is greater than the package list length. Likewise,
 151          * Package is truncated if num_elements is less than the list length.
 152          */
 153         for (i = 0; arg && (i < element_count); i++) {
 154                 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
 155                         if (!arg->common.node) {
 156                                 /*
 157                                  * This is the case where an expression has returned a value.
 158                                  * The use of expressions (term_args) within individual
 159                                  * package elements is not supported by the AML interpreter,
 160                                  * even though the ASL grammar supports it. Example:
 161                                  *
 162                                  *      Name (INT1, 0x1234)
 163                                  *
 164                                  *      Name (PKG3, Package () {
 165                                  *          Add (INT1, 0xAAAA0000)
 166                                  *      })
 167                                  *
 168                                  *  1) No known AML interpreter supports this type of construct
 169                                  *  2) This fixes a fault if the construct is encountered
 170                                  */
 171                                 ACPI_EXCEPTION((AE_INFO, AE_SUPPORT,
 172                                                 "Expressions within package elements are not supported"));
 173 
 174                                 /* Cleanup the return object, it is not needed */
 175 
 176                                 acpi_ut_remove_reference(walk_state->results->
 177                                                          results.obj_desc[0]);
 178                                 return_ACPI_STATUS(AE_SUPPORT);
 179                         }
 180 
 181                         if (arg->common.node->type == ACPI_TYPE_METHOD) {
 182                                 /*
 183                                  * A method reference "looks" to the parser to be a method
 184                                  * invocation, so we special case it here
 185                                  */
 186                                 arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
 187                                 status =
 188                                     acpi_ds_build_internal_object(walk_state,
 189                                                                   arg,
 190                                                                   &obj_desc->
 191                                                                   package.
 192                                                                   elements[i]);
 193                         } else {
 194                                 /* This package element is already built, just get it */
 195 
 196                                 obj_desc->package.elements[i] =
 197                                     ACPI_CAST_PTR(union acpi_operand_object,
 198                                                   arg->common.node);
 199                         }
 200                 } else {
 201                         status =
 202                             acpi_ds_build_internal_object(walk_state, arg,
 203                                                           &obj_desc->package.
 204                                                           elements[i]);
 205                         if (status == AE_NOT_FOUND) {
 206                                 ACPI_ERROR((AE_INFO, "%-48s",
 207                                             "****DS namepath not found"));
 208                         }
 209 
 210                         if (!module_level_code) {
 211                                 /*
 212                                  * Initialize this package element. This function handles the
 213                                  * resolution of named references within the package.
 214                                  * Forward references from module-level code are deferred
 215                                  * until all ACPI tables are loaded.
 216                                  */
 217                                 acpi_ds_init_package_element(0,
 218                                                              obj_desc->package.
 219                                                              elements[i], NULL,
 220                                                              &obj_desc->package.
 221                                                              elements[i]);
 222                         }
 223                 }
 224 
 225                 if (*obj_desc_ptr) {
 226 
 227                         /* Existing package, get existing reference count */
 228 
 229                         reference_count =
 230                             (*obj_desc_ptr)->common.reference_count;
 231                         if (reference_count > 1) {
 232 
 233                                 /* Make new element ref count match original ref count */
 234                                 /* TBD: Probably need an acpi_ut_add_references function */
 235 
 236                                 for (index = 0;
 237                                      index < ((u32)reference_count - 1);
 238                                      index++) {
 239                                         acpi_ut_add_reference((obj_desc->
 240                                                                package.
 241                                                                elements[i]));
 242                                 }
 243                         }
 244                 }
 245 
 246                 arg = arg->common.next;
 247         }
 248 
 249         /* Check for match between num_elements and actual length of package_list */
 250 
 251         if (arg) {
 252                 /*
 253                  * num_elements was exhausted, but there are remaining elements in
 254                  * the package_list. Truncate the package to num_elements.
 255                  *
 256                  * Note: technically, this is an error, from ACPI spec: "It is an
 257                  * error for NumElements to be less than the number of elements in
 258                  * the PackageList". However, we just print a message and no
 259                  * exception is returned. This provides compatibility with other
 260                  * ACPI implementations. Some firmware implementations will alter
 261                  * the num_elements on the fly, possibly creating this type of
 262                  * ill-formed package object.
 263                  */
 264                 while (arg) {
 265                         /*
 266                          * We must delete any package elements that were created earlier
 267                          * and are not going to be used because of the package truncation.
 268                          */
 269                         if (arg->common.node) {
 270                                 acpi_ut_remove_reference(ACPI_CAST_PTR
 271                                                          (union
 272                                                           acpi_operand_object,
 273                                                           arg->common.node));
 274                                 arg->common.node = NULL;
 275                         }
 276 
 277                         /* Find out how many elements there really are */
 278 
 279                         i++;
 280                         arg = arg->common.next;
 281                 }
 282 
 283                 ACPI_INFO(("Actual Package length (%u) is larger than "
 284                            "NumElements field (%u), truncated",
 285                            i, element_count));
 286         } else if (i < element_count) {
 287                 /*
 288                  * Arg list (elements) was exhausted, but we did not reach
 289                  * num_elements count.
 290                  *
 291                  * Note: this is not an error, the package is padded out
 292                  * with NULLs as per the ACPI specification.
 293                  */
 294                 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
 295                                       "%s: Package List length (%u) smaller than NumElements "
 296                                       "count (%u), padded with null elements\n",
 297                                       ACPI_GET_FUNCTION_NAME, i,
 298                                       element_count));
 299         }
 300 
 301         /* Module-level packages will be resolved later */
 302 
 303         if (!module_level_code) {
 304                 obj_desc->package.flags |= AOPOBJ_DATA_VALID;
 305         }
 306 
 307         op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
 308         return_ACPI_STATUS(status);
 309 }
 310 
 311 /*******************************************************************************
 312  *
 313  * FUNCTION:    acpi_ds_init_package_element
 314  *
 315  * PARAMETERS:  acpi_pkg_callback
 316  *
 317  * RETURN:      Status
 318  *
 319  * DESCRIPTION: Resolve a named reference element within a package object
 320  *
 321  ******************************************************************************/
 322 
 323 acpi_status
 324 acpi_ds_init_package_element(u8 object_type,
 325                              union acpi_operand_object *source_object,
 326                              union acpi_generic_state *state, void *context)
 327 {
 328         union acpi_operand_object **element_ptr;
 329 
 330         ACPI_FUNCTION_TRACE(ds_init_package_element);
 331 
 332         if (!source_object) {
 333                 return_ACPI_STATUS(AE_OK);
 334         }
 335 
 336         /*
 337          * The following code is a bit of a hack to workaround a (current)
 338          * limitation of the acpi_pkg_callback interface. We need a pointer
 339          * to the location within the element array because a new object
 340          * may be created and stored there.
 341          */
 342         if (context) {
 343 
 344                 /* A direct call was made to this function */
 345 
 346                 element_ptr = (union acpi_operand_object **)context;
 347         } else {
 348                 /* Call came from acpi_ut_walk_package_tree */
 349 
 350                 element_ptr = state->pkg.this_target_obj;
 351         }
 352 
 353         /* We are only interested in reference objects/elements */
 354 
 355         if (source_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
 356 
 357                 /* Attempt to resolve the (named) reference to a namespace node */
 358 
 359                 acpi_ds_resolve_package_element(element_ptr);
 360         } else if (source_object->common.type == ACPI_TYPE_PACKAGE) {
 361                 source_object->package.flags |= AOPOBJ_DATA_VALID;
 362         }
 363 
 364         return_ACPI_STATUS(AE_OK);
 365 }
 366 
 367 /*******************************************************************************
 368  *
 369  * FUNCTION:    acpi_ds_resolve_package_element
 370  *
 371  * PARAMETERS:  element_ptr         - Pointer to a reference object
 372  *
 373  * RETURN:      Possible new element is stored to the indirect element_ptr
 374  *
 375  * DESCRIPTION: Resolve a package element that is a reference to a named
 376  *              object.
 377  *
 378  ******************************************************************************/
 379 
 380 static void
 381 acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
 382 {
 383         acpi_status status;
 384         acpi_status status2;
 385         union acpi_generic_state scope_info;
 386         union acpi_operand_object *element = *element_ptr;
 387         struct acpi_namespace_node *resolved_node;
 388         struct acpi_namespace_node *original_node;
 389         char *external_path = "";
 390         acpi_object_type type;
 391 
 392         ACPI_FUNCTION_TRACE(ds_resolve_package_element);
 393 
 394         /* Check if reference element is already resolved */
 395 
 396         if (element->reference.resolved) {
 397                 ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
 398                                       "%s: Package element is already resolved\n",
 399                                       ACPI_GET_FUNCTION_NAME));
 400 
 401                 return_VOID;
 402         }
 403 
 404         /* Element must be a reference object of correct type */
 405 
 406         scope_info.scope.node = element->reference.node;        /* Prefix node */
 407 
 408         status = acpi_ns_lookup(&scope_info, (char *)element->reference.aml,
 409                                 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
 410                                 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
 411                                 NULL, &resolved_node);
 412         if (ACPI_FAILURE(status)) {
 413                 if ((status == AE_NOT_FOUND)
 414                     && acpi_gbl_ignore_package_resolution_errors) {
 415                         /*
 416                          * Optionally be silent about the NOT_FOUND case for the referenced
 417                          * name. Although this is potentially a serious problem,
 418                          * it can generate a lot of noise/errors on platforms whose
 419                          * firmware carries around a bunch of unused Package objects.
 420                          * To disable these errors, set this global to TRUE:
 421                          *     acpi_gbl_ignore_package_resolution_errors
 422                          *
 423                          * If the AML actually tries to use such a package, the unresolved
 424                          * element(s) will be replaced with NULL elements.
 425                          */
 426 
 427                         /* Referenced name not found, set the element to NULL */
 428 
 429                         acpi_ut_remove_reference(*element_ptr);
 430                         *element_ptr = NULL;
 431                         return_VOID;
 432                 }
 433 
 434                 status2 = acpi_ns_externalize_name(ACPI_UINT32_MAX,
 435                                                    (char *)element->reference.
 436                                                    aml, NULL, &external_path);
 437 
 438                 ACPI_EXCEPTION((AE_INFO, status,
 439                                 "While resolving a named reference package element - %s",
 440                                 external_path));
 441                 if (ACPI_SUCCESS(status2)) {
 442                         ACPI_FREE(external_path);
 443                 }
 444 
 445                 /* Could not resolve name, set the element to NULL */
 446 
 447                 acpi_ut_remove_reference(*element_ptr);
 448                 *element_ptr = NULL;
 449                 return_VOID;
 450         } else if (resolved_node->type == ACPI_TYPE_ANY) {
 451 
 452                 /* Named reference not resolved, return a NULL package element */
 453 
 454                 ACPI_ERROR((AE_INFO,
 455                             "Could not resolve named package element [%4.4s] in [%4.4s]",
 456                             resolved_node->name.ascii,
 457                             scope_info.scope.node->name.ascii));
 458                 *element_ptr = NULL;
 459                 return_VOID;
 460         }
 461 
 462         /*
 463          * Special handling for Alias objects. We need resolved_node to point
 464          * to the Alias target. This effectively "resolves" the alias.
 465          */
 466         if (resolved_node->type == ACPI_TYPE_LOCAL_ALIAS) {
 467                 resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node,
 468                                               resolved_node->object);
 469         }
 470 
 471         /* Update the reference object */
 472 
 473         element->reference.resolved = TRUE;
 474         element->reference.node = resolved_node;
 475         type = element->reference.node->type;
 476 
 477         /*
 478          * Attempt to resolve the node to a value before we insert it into
 479          * the package. If this is a reference to a common data type,
 480          * resolve it immediately. According to the ACPI spec, package
 481          * elements can only be "data objects" or method references.
 482          * Attempt to resolve to an Integer, Buffer, String or Package.
 483          * If cannot, return the named reference (for things like Devices,
 484          * Methods, etc.) Buffer Fields and Fields will resolve to simple
 485          * objects (int/buf/str/pkg).
 486          *
 487          * NOTE: References to things like Devices, Methods, Mutexes, etc.
 488          * will remain as named references. This behavior is not described
 489          * in the ACPI spec, but it appears to be an oversight.
 490          */
 491         original_node = resolved_node;
 492         status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
 493         if (ACPI_FAILURE(status)) {
 494                 return_VOID;
 495         }
 496 
 497         switch (type) {
 498                 /*
 499                  * These object types are a result of named references, so we will
 500                  * leave them as reference objects. In other words, these types
 501                  * have no intrinsic "value".
 502                  */
 503         case ACPI_TYPE_DEVICE:
 504         case ACPI_TYPE_THERMAL:
 505         case ACPI_TYPE_METHOD:
 506                 break;
 507 
 508         case ACPI_TYPE_MUTEX:
 509         case ACPI_TYPE_POWER:
 510         case ACPI_TYPE_PROCESSOR:
 511         case ACPI_TYPE_EVENT:
 512         case ACPI_TYPE_REGION:
 513 
 514                 /* acpi_ex_resolve_node_to_value gave these an extra reference */
 515 
 516                 acpi_ut_remove_reference(original_node->object);
 517                 break;
 518 
 519         default:
 520                 /*
 521                  * For all other types - the node was resolved to an actual
 522                  * operand object with a value, return the object. Remove
 523                  * a reference on the existing object.
 524                  */
 525                 acpi_ut_remove_reference(element);
 526                 *element_ptr = (union acpi_operand_object *)resolved_node;
 527                 break;
 528         }
 529 
 530         return_VOID;
 531 }

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