linux/drivers/acpi/acpica/nseval.c
<<
>>
Prefs
   1/*******************************************************************************
   2 *
   3 * Module Name: nseval - Object evaluation, includes control method execution
   4 *
   5 ******************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2008, Intel Corp.
   9 * All rights reserved.
  10 *
  11 * Redistribution and use in source and binary forms, with or without
  12 * modification, are permitted provided that the following conditions
  13 * are met:
  14 * 1. Redistributions of source code must retain the above copyright
  15 *    notice, this list of conditions, and the following disclaimer,
  16 *    without modification.
  17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18 *    substantially similar to the "NO WARRANTY" disclaimer below
  19 *    ("Disclaimer") and any redistribution must be conditioned upon
  20 *    including a substantially similar Disclaimer requirement for further
  21 *    binary redistribution.
  22 * 3. Neither the names of the above-listed copyright holders nor the names
  23 *    of any contributors may be used to endorse or promote products derived
  24 *    from this software without specific prior written permission.
  25 *
  26 * Alternatively, this software may be distributed under the terms of the
  27 * GNU General Public License ("GPL") version 2 as published by the Free
  28 * Software Foundation.
  29 *
  30 * NO WARRANTY
  31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41 * POSSIBILITY OF SUCH DAMAGES.
  42 */
  43
  44#include <acpi/acpi.h>
  45#include "accommon.h"
  46#include "acparser.h"
  47#include "acinterp.h"
  48#include "acnamesp.h"
  49
  50#define _COMPONENT          ACPI_NAMESPACE
  51ACPI_MODULE_NAME("nseval")
  52
  53/* Local prototypes */
  54static void
  55acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
  56                         struct acpi_evaluate_info *info);
  57
  58/*******************************************************************************
  59 *
  60 * FUNCTION:    acpi_ns_evaluate
  61 *
  62 * PARAMETERS:  Info            - Evaluation info block, contains:
  63 *                  prefix_node     - Prefix or Method/Object Node to execute
  64 *                  Pathname        - Name of method to execute, If NULL, the
  65 *                                    Node is the object to execute
  66 *                  Parameters      - List of parameters to pass to the method,
  67 *                                    terminated by NULL. Params itself may be
  68 *                                    NULL if no parameters are being passed.
  69 *                  return_object   - Where to put method's return value (if
  70 *                                    any). If NULL, no value is returned.
  71 *                  parameter_type  - Type of Parameter list
  72 *                  return_object   - Where to put method's return value (if
  73 *                                    any). If NULL, no value is returned.
  74 *                  Flags           - ACPI_IGNORE_RETURN_VALUE to delete return
  75 *
  76 * RETURN:      Status
  77 *
  78 * DESCRIPTION: Execute a control method or return the current value of an
  79 *              ACPI namespace object.
  80 *
  81 * MUTEX:       Locks interpreter
  82 *
  83 ******************************************************************************/
  84
  85acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
  86{
  87        acpi_status status;
  88        struct acpi_namespace_node *node;
  89
  90        ACPI_FUNCTION_TRACE(ns_evaluate);
  91
  92        if (!info) {
  93                return_ACPI_STATUS(AE_BAD_PARAMETER);
  94        }
  95
  96        /* Initialize the return value to an invalid object */
  97
  98        info->return_object = NULL;
  99        info->param_count = 0;
 100
 101        /*
 102         * Get the actual namespace node for the target object. Handles these cases:
 103         *
 104         * 1) Null node, Pathname (absolute path)
 105         * 2) Node, Pathname (path relative to Node)
 106         * 3) Node, Null Pathname
 107         */
 108        status = acpi_ns_get_node(info->prefix_node, info->pathname,
 109                                  ACPI_NS_NO_UPSEARCH, &info->resolved_node);
 110        if (ACPI_FAILURE(status)) {
 111                return_ACPI_STATUS(status);
 112        }
 113
 114        /*
 115         * For a method alias, we must grab the actual method node so that proper
 116         * scoping context will be established before execution.
 117         */
 118        if (acpi_ns_get_type(info->resolved_node) ==
 119            ACPI_TYPE_LOCAL_METHOD_ALIAS) {
 120                info->resolved_node =
 121                    ACPI_CAST_PTR(struct acpi_namespace_node,
 122                                  info->resolved_node->object);
 123        }
 124
 125        ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname,
 126                          info->resolved_node,
 127                          acpi_ns_get_attached_object(info->resolved_node)));
 128
 129        node = info->resolved_node;
 130
 131        /*
 132         * Two major cases here:
 133         *
 134         * 1) The object is a control method -- execute it
 135         * 2) The object is not a method -- just return it's current value
 136         */
 137        if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) {
 138                /*
 139                 * 1) Object is a control method - execute it
 140                 */
 141
 142                /* Verify that there is a method object associated with this node */
 143
 144                info->obj_desc =
 145                    acpi_ns_get_attached_object(info->resolved_node);
 146                if (!info->obj_desc) {
 147                        ACPI_ERROR((AE_INFO,
 148                                    "Control method has no attached sub-object"));
 149                        return_ACPI_STATUS(AE_NULL_OBJECT);
 150                }
 151
 152                /* Count the number of arguments being passed to the method */
 153
 154                if (info->parameters) {
 155                        while (info->parameters[info->param_count]) {
 156                                if (info->param_count > ACPI_METHOD_MAX_ARG) {
 157                                        return_ACPI_STATUS(AE_LIMIT);
 158                                }
 159                                info->param_count++;
 160                        }
 161                }
 162
 163
 164                ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method",
 165                                   ACPI_LV_INFO, _COMPONENT);
 166
 167                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 168                                  "Method at AML address %p Length %X\n",
 169                                  info->obj_desc->method.aml_start + 1,
 170                                  info->obj_desc->method.aml_length - 1));
 171
 172                /*
 173                 * Any namespace deletion must acquire both the namespace and
 174                 * interpreter locks to ensure that no thread is using the portion of
 175                 * the namespace that is being deleted.
 176                 *
 177                 * Execute the method via the interpreter. The interpreter is locked
 178                 * here before calling into the AML parser
 179                 */
 180                acpi_ex_enter_interpreter();
 181                status = acpi_ps_execute_method(info);
 182                acpi_ex_exit_interpreter();
 183        } else {
 184                /*
 185                 * 2) Object is not a method, return its current value
 186                 *
 187                 * Disallow certain object types. For these, "evaluation" is undefined.
 188                 */
 189                switch (info->resolved_node->type) {
 190                case ACPI_TYPE_DEVICE:
 191                case ACPI_TYPE_EVENT:
 192                case ACPI_TYPE_MUTEX:
 193                case ACPI_TYPE_REGION:
 194                case ACPI_TYPE_THERMAL:
 195                case ACPI_TYPE_LOCAL_SCOPE:
 196
 197                        ACPI_ERROR((AE_INFO,
 198                                    "[%4.4s] Evaluation of object type [%s] is not supported",
 199                                    info->resolved_node->name.ascii,
 200                                    acpi_ut_get_type_name(info->resolved_node->
 201                                                          type)));
 202
 203                        return_ACPI_STATUS(AE_TYPE);
 204
 205                default:
 206                        break;
 207                }
 208
 209                /*
 210                 * Objects require additional resolution steps (e.g., the Node may be
 211                 * a field that must be read, etc.) -- we can't just grab the object
 212                 * out of the node.
 213                 *
 214                 * Use resolve_node_to_value() to get the associated value.
 215                 *
 216                 * NOTE: we can get away with passing in NULL for a walk state because
 217                 * resolved_node is guaranteed to not be a reference to either a method
 218                 * local or a method argument (because this interface is never called
 219                 * from a running method.)
 220                 *
 221                 * Even though we do not directly invoke the interpreter for object
 222                 * resolution, we must lock it because we could access an opregion.
 223                 * The opregion access code assumes that the interpreter is locked.
 224                 */
 225                acpi_ex_enter_interpreter();
 226
 227                /* Function has a strange interface */
 228
 229                status =
 230                    acpi_ex_resolve_node_to_value(&info->resolved_node, NULL);
 231                acpi_ex_exit_interpreter();
 232
 233                /*
 234                 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed
 235                 * in resolved_node.
 236                 */
 237                if (ACPI_SUCCESS(status)) {
 238                        status = AE_CTRL_RETURN_VALUE;
 239                        info->return_object =
 240                            ACPI_CAST_PTR(union acpi_operand_object,
 241                                          info->resolved_node);
 242
 243                        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 244                                          "Returning object %p [%s]\n",
 245                                          info->return_object,
 246                                          acpi_ut_get_object_type_name(info->
 247                                                                       return_object)));
 248                }
 249        }
 250
 251        /*
 252         * Check input argument count against the ASL-defined count for a method.
 253         * Also check predefined names: argument count and return value against
 254         * the ACPI specification. Some incorrect return value types are repaired.
 255         */
 256        (void)acpi_ns_check_predefined_names(node, info->param_count,
 257                status, &info->return_object);
 258
 259        /* Check if there is a return value that must be dealt with */
 260
 261        if (status == AE_CTRL_RETURN_VALUE) {
 262
 263                /* If caller does not want the return value, delete it */
 264
 265                if (info->flags & ACPI_IGNORE_RETURN_VALUE) {
 266                        acpi_ut_remove_reference(info->return_object);
 267                        info->return_object = NULL;
 268                }
 269
 270                /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
 271
 272                status = AE_OK;
 273        }
 274
 275        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 276                          "*** Completed evaluation of object %s ***\n",
 277                          info->pathname));
 278
 279        /*
 280         * Namespace was unlocked by the handling acpi_ns* function, so we
 281         * just return
 282         */
 283        return_ACPI_STATUS(status);
 284}
 285
 286/*******************************************************************************
 287 *
 288 * FUNCTION:    acpi_ns_exec_module_code_list
 289 *
 290 * PARAMETERS:  None
 291 *
 292 * RETURN:      None. Exceptions during method execution are ignored, since
 293 *              we cannot abort a table load.
 294 *
 295 * DESCRIPTION: Execute all elements of the global module-level code list.
 296 *              Each element is executed as a single control method.
 297 *
 298 ******************************************************************************/
 299
 300void acpi_ns_exec_module_code_list(void)
 301{
 302        union acpi_operand_object *prev;
 303        union acpi_operand_object *next;
 304        struct acpi_evaluate_info *info;
 305        u32 method_count = 0;
 306
 307        ACPI_FUNCTION_TRACE(ns_exec_module_code_list);
 308
 309        /* Exit now if the list is empty */
 310
 311        next = acpi_gbl_module_code_list;
 312        if (!next) {
 313                return_VOID;
 314        }
 315
 316        /* Allocate the evaluation information block */
 317
 318        info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info));
 319        if (!info) {
 320                return_VOID;
 321        }
 322
 323        /* Walk the list, executing each "method" */
 324
 325        while (next) {
 326                prev = next;
 327                next = next->method.mutex;
 328
 329                /* Clear the link field and execute the method */
 330
 331                prev->method.mutex = NULL;
 332                acpi_ns_exec_module_code(prev, info);
 333                method_count++;
 334
 335                /* Delete the (temporary) method object */
 336
 337                acpi_ut_remove_reference(prev);
 338        }
 339
 340        ACPI_INFO((AE_INFO,
 341                   "Executed %u blocks of module-level executable AML code",
 342                   method_count));
 343
 344        ACPI_FREE(info);
 345        acpi_gbl_module_code_list = NULL;
 346        return_VOID;
 347}
 348
 349/*******************************************************************************
 350 *
 351 * FUNCTION:    acpi_ns_exec_module_code
 352 *
 353 * PARAMETERS:  method_obj          - Object container for the module-level code
 354 *              Info                - Info block for method evaluation
 355 *
 356 * RETURN:      None. Exceptions during method execution are ignored, since
 357 *              we cannot abort a table load.
 358 *
 359 * DESCRIPTION: Execute a control method containing a block of module-level
 360 *              executable AML code. The control method is temporarily
 361 *              installed to the root node, then evaluated.
 362 *
 363 ******************************************************************************/
 364
 365static void
 366acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
 367                         struct acpi_evaluate_info *info)
 368{
 369        union acpi_operand_object *root_obj;
 370        acpi_status status;
 371
 372        ACPI_FUNCTION_TRACE(ns_exec_module_code);
 373
 374        /* Initialize the evaluation information block */
 375
 376        ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
 377        info->prefix_node = acpi_gbl_root_node;
 378
 379        /*
 380         * Get the currently attached root object. Add a reference, because the
 381         * ref count will be decreased when the method object is installed to
 382         * the root node.
 383         */
 384        root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
 385        acpi_ut_add_reference(root_obj);
 386
 387        /* Install the method (module-level code) in the root node */
 388
 389        status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
 390                                       ACPI_TYPE_METHOD);
 391        if (ACPI_FAILURE(status)) {
 392                goto exit;
 393        }
 394
 395        /* Execute the root node as a control method */
 396
 397        status = acpi_ns_evaluate(info);
 398
 399        ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
 400                          method_obj->method.aml_start));
 401
 402        /* Detach the temporary method object */
 403
 404        acpi_ns_detach_object(acpi_gbl_root_node);
 405
 406        /* Restore the original root object */
 407
 408        status =
 409            acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
 410                                  ACPI_TYPE_DEVICE);
 411
 412      exit:
 413        acpi_ut_remove_reference(root_obj);
 414        return_VOID;
 415}
 416