Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: dspkginit - Completion of deferred package initialization
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acnamesp.h"
0013 #include "amlcode.h"
0014 #include "acdispat.h"
0015 #include "acinterp.h"
0016 #include "acparser.h"
0017 
0018 #define _COMPONENT          ACPI_NAMESPACE
0019 ACPI_MODULE_NAME("dspkginit")
0020 
0021 /* Local prototypes */
0022 static void
0023 acpi_ds_resolve_package_element(union acpi_operand_object **element);
0024 
0025 /*******************************************************************************
0026  *
0027  * FUNCTION:    acpi_ds_build_internal_package_obj
0028  *
0029  * PARAMETERS:  walk_state      - Current walk state
0030  *              op              - Parser object to be translated
0031  *              element_count   - Number of elements in the package - this is
0032  *                                the num_elements argument to Package()
0033  *              obj_desc_ptr    - Where the ACPI internal object is returned
0034  *
0035  * RETURN:      Status
0036  *
0037  * DESCRIPTION: Translate a parser Op package object to the equivalent
0038  *              namespace object
0039  *
0040  * NOTE: The number of elements in the package will be always be the num_elements
0041  * count, regardless of the number of elements in the package list. If
0042  * num_elements is smaller, only that many package list elements are used.
0043  * if num_elements is larger, the Package object is padded out with
0044  * objects of type Uninitialized (as per ACPI spec.)
0045  *
0046  * Even though the ASL compilers do not allow num_elements to be smaller
0047  * than the Package list length (for the fixed length package opcode), some
0048  * BIOS code modifies the AML on the fly to adjust the num_elements, and
0049  * this code compensates for that. This also provides compatibility with
0050  * other AML interpreters.
0051  *
0052  ******************************************************************************/
0053 
0054 acpi_status
0055 acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
0056                    union acpi_parse_object *op,
0057                    u32 element_count,
0058                    union acpi_operand_object **obj_desc_ptr)
0059 {
0060     union acpi_parse_object *arg;
0061     union acpi_parse_object *parent;
0062     union acpi_operand_object *obj_desc = NULL;
0063     acpi_status status = AE_OK;
0064     u8 module_level_code = FALSE;
0065     u16 reference_count;
0066     u32 index;
0067     u32 i;
0068 
0069     ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
0070 
0071     /* Check if we are executing module level code */
0072 
0073     if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) {
0074         module_level_code = TRUE;
0075     }
0076 
0077     /* Find the parent of a possibly nested package */
0078 
0079     parent = op->common.parent;
0080     while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
0081            (parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
0082         parent = parent->common.parent;
0083     }
0084 
0085     /*
0086      * If we are evaluating a Named package object of the form:
0087      *      Name (xxxx, Package)
0088      * the package object already exists, otherwise it must be created.
0089      */
0090     obj_desc = *obj_desc_ptr;
0091     if (!obj_desc) {
0092         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
0093         *obj_desc_ptr = obj_desc;
0094         if (!obj_desc) {
0095             return_ACPI_STATUS(AE_NO_MEMORY);
0096         }
0097 
0098         obj_desc->package.node = parent->common.node;
0099     }
0100 
0101     if (obj_desc->package.flags & AOPOBJ_DATA_VALID) {  /* Just in case */
0102         return_ACPI_STATUS(AE_OK);
0103     }
0104 
0105     /*
0106      * Allocate the element array (array of pointers to the individual
0107      * objects) if necessary. the count is based on the num_elements
0108      * parameter. Add an extra pointer slot so that the list is always
0109      * null terminated.
0110      */
0111     if (!obj_desc->package.elements) {
0112         obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
0113                                    element_count
0114                                    +
0115                                    1) *
0116                                   sizeof(void
0117                                      *));
0118 
0119         if (!obj_desc->package.elements) {
0120             acpi_ut_delete_object_desc(obj_desc);
0121             return_ACPI_STATUS(AE_NO_MEMORY);
0122         }
0123 
0124         obj_desc->package.count = element_count;
0125     }
0126 
0127     /* First arg is element count. Second arg begins the initializer list */
0128 
0129     arg = op->common.value.arg;
0130     arg = arg->common.next;
0131 
0132     /*
0133      * If we are executing module-level code, we will defer the
0134      * full resolution of the package elements in order to support
0135      * forward references from the elements. This provides
0136      * compatibility with other ACPI implementations.
0137      */
0138     if (module_level_code) {
0139         obj_desc->package.aml_start = walk_state->aml;
0140         obj_desc->package.aml_length = 0;
0141 
0142         ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
0143                       "%s: Deferring resolution of Package elements\n",
0144                       ACPI_GET_FUNCTION_NAME));
0145     }
0146 
0147     /*
0148      * Initialize the elements of the package, up to the num_elements count.
0149      * Package is automatically padded with uninitialized (NULL) elements
0150      * if num_elements is greater than the package list length. Likewise,
0151      * Package is truncated if num_elements is less than the list length.
0152      */
0153     for (i = 0; arg && (i < element_count); i++) {
0154         if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
0155             if (!arg->common.node) {
0156                 /*
0157                  * This is the case where an expression has returned a value.
0158                  * The use of expressions (term_args) within individual
0159                  * package elements is not supported by the AML interpreter,
0160                  * even though the ASL grammar supports it. Example:
0161                  *
0162                  *      Name (INT1, 0x1234)
0163                  *
0164                  *      Name (PKG3, Package () {
0165                  *          Add (INT1, 0xAAAA0000)
0166                  *      })
0167                  *
0168                  *  1) No known AML interpreter supports this type of construct
0169                  *  2) This fixes a fault if the construct is encountered
0170                  */
0171                 ACPI_EXCEPTION((AE_INFO, AE_SUPPORT,
0172                         "Expressions within package elements are not supported"));
0173 
0174                 /* Cleanup the return object, it is not needed */
0175 
0176                 acpi_ut_remove_reference(walk_state->results->
0177                              results.obj_desc[0]);
0178                 return_ACPI_STATUS(AE_SUPPORT);
0179             }
0180 
0181             if (arg->common.node->type == ACPI_TYPE_METHOD) {
0182                 /*
0183                  * A method reference "looks" to the parser to be a method
0184                  * invocation, so we special case it here
0185                  */
0186                 arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
0187                 status =
0188                     acpi_ds_build_internal_object(walk_state,
0189                                   arg,
0190                                   &obj_desc->
0191                                   package.
0192                                   elements[i]);
0193             } else {
0194                 /* This package element is already built, just get it */
0195 
0196                 obj_desc->package.elements[i] =
0197                     ACPI_CAST_PTR(union acpi_operand_object,
0198                           arg->common.node);
0199             }
0200         } else {
0201             status =
0202                 acpi_ds_build_internal_object(walk_state, arg,
0203                               &obj_desc->package.
0204                               elements[i]);
0205             if (status == AE_NOT_FOUND) {
0206                 ACPI_ERROR((AE_INFO, "%-48s",
0207                         "****DS namepath not found"));
0208             }
0209 
0210             if (!module_level_code) {
0211                 /*
0212                  * Initialize this package element. This function handles the
0213                  * resolution of named references within the package.
0214                  * Forward references from module-level code are deferred
0215                  * until all ACPI tables are loaded.
0216                  */
0217                 acpi_ds_init_package_element(0,
0218                                  obj_desc->package.
0219                                  elements[i], NULL,
0220                                  &obj_desc->package.
0221                                  elements[i]);
0222             }
0223         }
0224 
0225         if (*obj_desc_ptr) {
0226 
0227             /* Existing package, get existing reference count */
0228 
0229             reference_count =
0230                 (*obj_desc_ptr)->common.reference_count;
0231             if (reference_count > 1) {
0232 
0233                 /* Make new element ref count match original ref count */
0234                 /* TBD: Probably need an acpi_ut_add_references function */
0235 
0236                 for (index = 0;
0237                      index < ((u32)reference_count - 1);
0238                      index++) {
0239                     acpi_ut_add_reference((obj_desc->
0240                                    package.
0241                                    elements[i]));
0242                 }
0243             }
0244         }
0245 
0246         arg = arg->common.next;
0247     }
0248 
0249     /* Check for match between num_elements and actual length of package_list */
0250 
0251     if (arg) {
0252         /*
0253          * num_elements was exhausted, but there are remaining elements in
0254          * the package_list. Truncate the package to num_elements.
0255          *
0256          * Note: technically, this is an error, from ACPI spec: "It is an
0257          * error for NumElements to be less than the number of elements in
0258          * the PackageList". However, we just print a message and no
0259          * exception is returned. This provides compatibility with other
0260          * ACPI implementations. Some firmware implementations will alter
0261          * the num_elements on the fly, possibly creating this type of
0262          * ill-formed package object.
0263          */
0264         while (arg) {
0265             /*
0266              * We must delete any package elements that were created earlier
0267              * and are not going to be used because of the package truncation.
0268              */
0269             if (arg->common.node) {
0270                 acpi_ut_remove_reference(ACPI_CAST_PTR
0271                              (union
0272                               acpi_operand_object,
0273                               arg->common.node));
0274                 arg->common.node = NULL;
0275             }
0276 
0277             /* Find out how many elements there really are */
0278 
0279             i++;
0280             arg = arg->common.next;
0281         }
0282 
0283         ACPI_INFO(("Actual Package length (%u) is larger than "
0284                "NumElements field (%u), truncated",
0285                i, element_count));
0286     } else if (i < element_count) {
0287         /*
0288          * Arg list (elements) was exhausted, but we did not reach
0289          * num_elements count.
0290          *
0291          * Note: this is not an error, the package is padded out
0292          * with NULLs as per the ACPI specification.
0293          */
0294         ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
0295                       "%s: Package List length (%u) smaller than NumElements "
0296                       "count (%u), padded with null elements\n",
0297                       ACPI_GET_FUNCTION_NAME, i,
0298                       element_count));
0299     }
0300 
0301     /* Module-level packages will be resolved later */
0302 
0303     if (!module_level_code) {
0304         obj_desc->package.flags |= AOPOBJ_DATA_VALID;
0305     }
0306 
0307     op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
0308     return_ACPI_STATUS(status);
0309 }
0310 
0311 /*******************************************************************************
0312  *
0313  * FUNCTION:    acpi_ds_init_package_element
0314  *
0315  * PARAMETERS:  acpi_pkg_callback
0316  *
0317  * RETURN:      Status
0318  *
0319  * DESCRIPTION: Resolve a named reference element within a package object
0320  *
0321  ******************************************************************************/
0322 
0323 acpi_status
0324 acpi_ds_init_package_element(u8 object_type,
0325                  union acpi_operand_object *source_object,
0326                  union acpi_generic_state *state, void *context)
0327 {
0328     union acpi_operand_object **element_ptr;
0329 
0330     ACPI_FUNCTION_TRACE(ds_init_package_element);
0331 
0332     if (!source_object) {
0333         return_ACPI_STATUS(AE_OK);
0334     }
0335 
0336     /*
0337      * The following code is a bit of a hack to workaround a (current)
0338      * limitation of the acpi_pkg_callback interface. We need a pointer
0339      * to the location within the element array because a new object
0340      * may be created and stored there.
0341      */
0342     if (context) {
0343 
0344         /* A direct call was made to this function */
0345 
0346         element_ptr = (union acpi_operand_object **)context;
0347     } else {
0348         /* Call came from acpi_ut_walk_package_tree */
0349 
0350         element_ptr = state->pkg.this_target_obj;
0351     }
0352 
0353     /* We are only interested in reference objects/elements */
0354 
0355     if (source_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
0356 
0357         /* Attempt to resolve the (named) reference to a namespace node */
0358 
0359         acpi_ds_resolve_package_element(element_ptr);
0360     } else if (source_object->common.type == ACPI_TYPE_PACKAGE) {
0361         source_object->package.flags |= AOPOBJ_DATA_VALID;
0362     }
0363 
0364     return_ACPI_STATUS(AE_OK);
0365 }
0366 
0367 /*******************************************************************************
0368  *
0369  * FUNCTION:    acpi_ds_resolve_package_element
0370  *
0371  * PARAMETERS:  element_ptr         - Pointer to a reference object
0372  *
0373  * RETURN:      Possible new element is stored to the indirect element_ptr
0374  *
0375  * DESCRIPTION: Resolve a package element that is a reference to a named
0376  *              object.
0377  *
0378  ******************************************************************************/
0379 
0380 static void
0381 acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
0382 {
0383     acpi_status status;
0384     acpi_status status2;
0385     union acpi_generic_state scope_info;
0386     union acpi_operand_object *element = *element_ptr;
0387     struct acpi_namespace_node *resolved_node;
0388     struct acpi_namespace_node *original_node;
0389     char *external_path = "";
0390     acpi_object_type type;
0391 
0392     ACPI_FUNCTION_TRACE(ds_resolve_package_element);
0393 
0394     /* Check if reference element is already resolved */
0395 
0396     if (element->reference.resolved) {
0397         ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
0398                       "%s: Package element is already resolved\n",
0399                       ACPI_GET_FUNCTION_NAME));
0400 
0401         return_VOID;
0402     }
0403 
0404     /* Element must be a reference object of correct type */
0405 
0406     scope_info.scope.node = element->reference.node;    /* Prefix node */
0407 
0408     status = acpi_ns_lookup(&scope_info, (char *)element->reference.aml,
0409                 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
0410                 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
0411                 NULL, &resolved_node);
0412     if (ACPI_FAILURE(status)) {
0413         if ((status == AE_NOT_FOUND)
0414             && acpi_gbl_ignore_package_resolution_errors) {
0415             /*
0416              * Optionally be silent about the NOT_FOUND case for the referenced
0417              * name. Although this is potentially a serious problem,
0418              * it can generate a lot of noise/errors on platforms whose
0419              * firmware carries around a bunch of unused Package objects.
0420              * To disable these errors, set this global to TRUE:
0421              *     acpi_gbl_ignore_package_resolution_errors
0422              *
0423              * If the AML actually tries to use such a package, the unresolved
0424              * element(s) will be replaced with NULL elements.
0425              */
0426 
0427             /* Referenced name not found, set the element to NULL */
0428 
0429             acpi_ut_remove_reference(*element_ptr);
0430             *element_ptr = NULL;
0431             return_VOID;
0432         }
0433 
0434         status2 = acpi_ns_externalize_name(ACPI_UINT32_MAX,
0435                            (char *)element->reference.
0436                            aml, NULL, &external_path);
0437 
0438         ACPI_EXCEPTION((AE_INFO, status,
0439                 "While resolving a named reference package element - %s",
0440                 external_path));
0441         if (ACPI_SUCCESS(status2)) {
0442             ACPI_FREE(external_path);
0443         }
0444 
0445         /* Could not resolve name, set the element to NULL */
0446 
0447         acpi_ut_remove_reference(*element_ptr);
0448         *element_ptr = NULL;
0449         return_VOID;
0450     } else if (resolved_node->type == ACPI_TYPE_ANY) {
0451 
0452         /* Named reference not resolved, return a NULL package element */
0453 
0454         ACPI_ERROR((AE_INFO,
0455                 "Could not resolve named package element [%4.4s] in [%4.4s]",
0456                 resolved_node->name.ascii,
0457                 scope_info.scope.node->name.ascii));
0458         *element_ptr = NULL;
0459         return_VOID;
0460     }
0461 
0462     /*
0463      * Special handling for Alias objects. We need resolved_node to point
0464      * to the Alias target. This effectively "resolves" the alias.
0465      */
0466     if (resolved_node->type == ACPI_TYPE_LOCAL_ALIAS) {
0467         resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node,
0468                           resolved_node->object);
0469     }
0470 
0471     /* Update the reference object */
0472 
0473     element->reference.resolved = TRUE;
0474     element->reference.node = resolved_node;
0475     type = element->reference.node->type;
0476 
0477     /*
0478      * Attempt to resolve the node to a value before we insert it into
0479      * the package. If this is a reference to a common data type,
0480      * resolve it immediately. According to the ACPI spec, package
0481      * elements can only be "data objects" or method references.
0482      * Attempt to resolve to an Integer, Buffer, String or Package.
0483      * If cannot, return the named reference (for things like Devices,
0484      * Methods, etc.) Buffer Fields and Fields will resolve to simple
0485      * objects (int/buf/str/pkg).
0486      *
0487      * NOTE: References to things like Devices, Methods, Mutexes, etc.
0488      * will remain as named references. This behavior is not described
0489      * in the ACPI spec, but it appears to be an oversight.
0490      */
0491     original_node = resolved_node;
0492     status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
0493     if (ACPI_FAILURE(status)) {
0494         return_VOID;
0495     }
0496 
0497     switch (type) {
0498         /*
0499          * These object types are a result of named references, so we will
0500          * leave them as reference objects. In other words, these types
0501          * have no intrinsic "value".
0502          */
0503     case ACPI_TYPE_DEVICE:
0504     case ACPI_TYPE_THERMAL:
0505     case ACPI_TYPE_METHOD:
0506         break;
0507 
0508     case ACPI_TYPE_MUTEX:
0509     case ACPI_TYPE_POWER:
0510     case ACPI_TYPE_PROCESSOR:
0511     case ACPI_TYPE_EVENT:
0512     case ACPI_TYPE_REGION:
0513 
0514         /* acpi_ex_resolve_node_to_value gave these an extra reference */
0515 
0516         acpi_ut_remove_reference(original_node->object);
0517         break;
0518 
0519     default:
0520         /*
0521          * For all other types - the node was resolved to an actual
0522          * operand object with a value, return the object. Remove
0523          * a reference on the existing object.
0524          */
0525         acpi_ut_remove_reference(element);
0526         *element_ptr = (union acpi_operand_object *)resolved_node;
0527         break;
0528     }
0529 
0530     return_VOID;
0531 }