Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /*******************************************************************************
0003  *
0004  * Module Name: nseval - Object evaluation, includes control method execution
0005  *
0006  ******************************************************************************/
0007 
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acparser.h"
0011 #include "acinterp.h"
0012 #include "acnamesp.h"
0013 
0014 #define _COMPONENT          ACPI_NAMESPACE
0015 ACPI_MODULE_NAME("nseval")
0016 
0017 /*******************************************************************************
0018  *
0019  * FUNCTION:    acpi_ns_evaluate
0020  *
0021  * PARAMETERS:  info            - Evaluation info block, contains these fields
0022  *                                and more:
0023  *                  prefix_node     - Prefix or Method/Object Node to execute
0024  *                  relative_path   - Name of method to execute, If NULL, the
0025  *                                    Node is the object to execute
0026  *                  parameters      - List of parameters to pass to the method,
0027  *                                    terminated by NULL. Params itself may be
0028  *                                    NULL if no parameters are being passed.
0029  *                  parameter_type  - Type of Parameter list
0030  *                  return_object   - Where to put method's return value (if
0031  *                                    any). If NULL, no value is returned.
0032  *                  flags           - ACPI_IGNORE_RETURN_VALUE to delete return
0033  *
0034  * RETURN:      Status
0035  *
0036  * DESCRIPTION: Execute a control method or return the current value of an
0037  *              ACPI namespace object.
0038  *
0039  * MUTEX:       Locks interpreter
0040  *
0041  ******************************************************************************/
0042 acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
0043 {
0044     acpi_status status;
0045 
0046     ACPI_FUNCTION_TRACE(ns_evaluate);
0047 
0048     if (!info) {
0049         return_ACPI_STATUS(AE_BAD_PARAMETER);
0050     }
0051 
0052     if (!info->node) {
0053         /*
0054          * Get the actual namespace node for the target object if we
0055          * need to. Handles these cases:
0056          *
0057          * 1) Null node, valid pathname from root (absolute path)
0058          * 2) Node and valid pathname (path relative to Node)
0059          * 3) Node, Null pathname
0060          */
0061         status =
0062             acpi_ns_get_node(info->prefix_node, info->relative_pathname,
0063                      ACPI_NS_NO_UPSEARCH, &info->node);
0064         if (ACPI_FAILURE(status)) {
0065             return_ACPI_STATUS(status);
0066         }
0067     }
0068 
0069     /*
0070      * For a method alias, we must grab the actual method node so that
0071      * proper scoping context will be established before execution.
0072      */
0073     if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
0074         info->node =
0075             ACPI_CAST_PTR(struct acpi_namespace_node,
0076                   info->node->object);
0077     }
0078 
0079     /* Complete the info block initialization */
0080 
0081     info->return_object = NULL;
0082     info->node_flags = info->node->flags;
0083     info->obj_desc = acpi_ns_get_attached_object(info->node);
0084 
0085     ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
0086               info->relative_pathname, info->node,
0087               acpi_ns_get_attached_object(info->node)));
0088 
0089     /* Get info if we have a predefined name (_HID, etc.) */
0090 
0091     info->predefined =
0092         acpi_ut_match_predefined_method(info->node->name.ascii);
0093 
0094     /* Get the full pathname to the object, for use in warning messages */
0095 
0096     info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
0097     if (!info->full_pathname) {
0098         return_ACPI_STATUS(AE_NO_MEMORY);
0099     }
0100 
0101     /* Optional object evaluation log */
0102 
0103     ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
0104                   "%-26s:  %s (%s)\n", "   Enter evaluation",
0105                   &info->full_pathname[1],
0106                   acpi_ut_get_type_name(info->node->type)));
0107 
0108     /* Count the number of arguments being passed in */
0109 
0110     info->param_count = 0;
0111     if (info->parameters) {
0112         while (info->parameters[info->param_count]) {
0113             info->param_count++;
0114         }
0115 
0116         /* Warn on impossible argument count */
0117 
0118         if (info->param_count > ACPI_METHOD_NUM_ARGS) {
0119             ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
0120                           ACPI_WARN_ALWAYS,
0121                           "Excess arguments (%u) - using only %u",
0122                           info->param_count,
0123                           ACPI_METHOD_NUM_ARGS));
0124 
0125             info->param_count = ACPI_METHOD_NUM_ARGS;
0126         }
0127     }
0128 
0129     /*
0130      * For predefined names: Check that the declared argument count
0131      * matches the ACPI spec -- otherwise this is a BIOS error.
0132      */
0133     acpi_ns_check_acpi_compliance(info->full_pathname, info->node,
0134                       info->predefined);
0135 
0136     /*
0137      * For all names: Check that the incoming argument count for
0138      * this method/object matches the actual ASL/AML definition.
0139      */
0140     acpi_ns_check_argument_count(info->full_pathname, info->node,
0141                      info->param_count, info->predefined);
0142 
0143     /* For predefined names: Typecheck all incoming arguments */
0144 
0145     acpi_ns_check_argument_types(info);
0146 
0147     /*
0148      * Three major evaluation cases:
0149      *
0150      * 1) Object types that cannot be evaluated by definition
0151      * 2) The object is a control method -- execute it
0152      * 3) The object is not a method -- just return it's current value
0153      */
0154     switch (acpi_ns_get_type(info->node)) {
0155     case ACPI_TYPE_ANY:
0156     case ACPI_TYPE_DEVICE:
0157     case ACPI_TYPE_EVENT:
0158     case ACPI_TYPE_MUTEX:
0159     case ACPI_TYPE_REGION:
0160     case ACPI_TYPE_THERMAL:
0161     case ACPI_TYPE_LOCAL_SCOPE:
0162         /*
0163          * 1) Disallow evaluation of these object types. For these,
0164          *    object evaluation is undefined.
0165          */
0166         ACPI_ERROR((AE_INFO,
0167                 "%s: This object type [%s] "
0168                 "never contains data and cannot be evaluated",
0169                 info->full_pathname,
0170                 acpi_ut_get_type_name(info->node->type)));
0171 
0172         status = AE_TYPE;
0173         goto cleanup;
0174 
0175     case ACPI_TYPE_METHOD:
0176         /*
0177          * 2) Object is a control method - execute it
0178          */
0179 
0180         /* Verify that there is a method object associated with this node */
0181 
0182         if (!info->obj_desc) {
0183             ACPI_ERROR((AE_INFO,
0184                     "%s: Method has no attached sub-object",
0185                     info->full_pathname));
0186             status = AE_NULL_OBJECT;
0187             goto cleanup;
0188         }
0189 
0190         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0191                   "**** Execute method [%s] at AML address %p length %X\n",
0192                   info->full_pathname,
0193                   info->obj_desc->method.aml_start + 1,
0194                   info->obj_desc->method.aml_length - 1));
0195 
0196         /*
0197          * Any namespace deletion must acquire both the namespace and
0198          * interpreter locks to ensure that no thread is using the portion of
0199          * the namespace that is being deleted.
0200          *
0201          * Execute the method via the interpreter. The interpreter is locked
0202          * here before calling into the AML parser
0203          */
0204         acpi_ex_enter_interpreter();
0205         status = acpi_ps_execute_method(info);
0206         acpi_ex_exit_interpreter();
0207         break;
0208 
0209     default:
0210         /*
0211          * 3) All other non-method objects -- get the current object value
0212          */
0213 
0214         /*
0215          * Some objects require additional resolution steps (e.g., the Node
0216          * may be a field that must be read, etc.) -- we can't just grab
0217          * the object out of the node.
0218          *
0219          * Use resolve_node_to_value() to get the associated value.
0220          *
0221          * NOTE: we can get away with passing in NULL for a walk state because
0222          * the Node is guaranteed to not be a reference to either a method
0223          * local or a method argument (because this interface is never called
0224          * from a running method.)
0225          *
0226          * Even though we do not directly invoke the interpreter for object
0227          * resolution, we must lock it because we could access an op_region.
0228          * The op_region access code assumes that the interpreter is locked.
0229          */
0230         acpi_ex_enter_interpreter();
0231 
0232         /* TBD: resolve_node_to_value has a strange interface, fix */
0233 
0234         info->return_object =
0235             ACPI_CAST_PTR(union acpi_operand_object, info->node);
0236 
0237         status =
0238             acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
0239                           (struct acpi_namespace_node,
0240                            &info->return_object), NULL);
0241         acpi_ex_exit_interpreter();
0242 
0243         if (ACPI_FAILURE(status)) {
0244             info->return_object = NULL;
0245             goto cleanup;
0246         }
0247 
0248         ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n",
0249                   info->return_object,
0250                   acpi_ut_get_object_type_name(info->
0251                                    return_object)));
0252 
0253         status = AE_CTRL_RETURN_VALUE;  /* Always has a "return value" */
0254         break;
0255     }
0256 
0257     /*
0258      * For predefined names, check the return value against the ACPI
0259      * specification. Some incorrect return value types are repaired.
0260      */
0261     (void)acpi_ns_check_return_value(info->node, info, info->param_count,
0262                      status, &info->return_object);
0263 
0264     /* Check if there is a return value that must be dealt with */
0265 
0266     if (status == AE_CTRL_RETURN_VALUE) {
0267 
0268         /* If caller does not want the return value, delete it */
0269 
0270         if (info->flags & ACPI_IGNORE_RETURN_VALUE) {
0271             acpi_ut_remove_reference(info->return_object);
0272             info->return_object = NULL;
0273         }
0274 
0275         /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
0276 
0277         status = AE_OK;
0278     } else if (ACPI_FAILURE(status)) {
0279 
0280         /* If return_object exists, delete it */
0281 
0282         if (info->return_object) {
0283             acpi_ut_remove_reference(info->return_object);
0284             info->return_object = NULL;
0285         }
0286     }
0287 
0288     ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
0289               "*** Completed evaluation of object %s ***\n",
0290               info->relative_pathname));
0291 
0292 cleanup:
0293     /* Optional object evaluation log */
0294 
0295     ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
0296                   "%-26s:  %s\n", "   Exit evaluation",
0297                   &info->full_pathname[1]));
0298 
0299     /*
0300      * Namespace was unlocked by the handling acpi_ns* function, so we
0301      * just free the pathname and return
0302      */
0303     ACPI_FREE(info->full_pathname);
0304     info->full_pathname = NULL;
0305     return_ACPI_STATUS(status);
0306 }