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 - 2015, 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 these fields
  63 *                                and more:
  64 *                  prefix_node     - Prefix or Method/Object Node to execute
  65 *                  relative_path   - Name of method to execute, If NULL, the
  66 *                                    Node is the object to execute
  67 *                  parameters      - List of parameters to pass to the method,
  68 *                                    terminated by NULL. Params itself may be
  69 *                                    NULL if no parameters are being passed.
  70 *                  parameter_type  - Type of Parameter list
  71 *                  return_object   - Where to put method's return value (if
  72 *                                    any). If NULL, no value is returned.
  73 *                  flags           - ACPI_IGNORE_RETURN_VALUE to delete return
  74 *
  75 * RETURN:      Status
  76 *
  77 * DESCRIPTION: Execute a control method or return the current value of an
  78 *              ACPI namespace object.
  79 *
  80 * MUTEX:       Locks interpreter
  81 *
  82 ******************************************************************************/
  83
  84acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
  85{
  86        acpi_status status;
  87
  88        ACPI_FUNCTION_TRACE(ns_evaluate);
  89
  90        if (!info) {
  91                return_ACPI_STATUS(AE_BAD_PARAMETER);
  92        }
  93
  94        if (!info->node) {
  95                /*
  96                 * Get the actual namespace node for the target object if we
  97                 * need to. Handles these cases:
  98                 *
  99                 * 1) Null node, valid pathname from root (absolute path)
 100                 * 2) Node and valid pathname (path relative to Node)
 101                 * 3) Node, Null pathname
 102                 */
 103                status =
 104                    acpi_ns_get_node(info->prefix_node, info->relative_pathname,
 105                                     ACPI_NS_NO_UPSEARCH, &info->node);
 106                if (ACPI_FAILURE(status)) {
 107                        return_ACPI_STATUS(status);
 108                }
 109        }
 110
 111        /*
 112         * For a method alias, we must grab the actual method node so that
 113         * proper scoping context will be established before execution.
 114         */
 115        if (acpi_ns_get_type(info->node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) {
 116                info->node =
 117                    ACPI_CAST_PTR(struct acpi_namespace_node,
 118                                  info->node->object);
 119        }
 120
 121        /* Complete the info block initialization */
 122
 123        info->return_object = NULL;
 124        info->node_flags = info->node->flags;
 125        info->obj_desc = acpi_ns_get_attached_object(info->node);
 126
 127        ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n",
 128                          info->relative_pathname, info->node,
 129                          acpi_ns_get_attached_object(info->node)));
 130
 131        /* Get info if we have a predefined name (_HID, etc.) */
 132
 133        info->predefined =
 134            acpi_ut_match_predefined_method(info->node->name.ascii);
 135
 136        /* Get the full pathname to the object, for use in warning messages */
 137
 138        info->full_pathname = acpi_ns_get_external_pathname(info->node);
 139        if (!info->full_pathname) {
 140                return_ACPI_STATUS(AE_NO_MEMORY);
 141        }
 142
 143        /* Count the number of arguments being passed in */
 144
 145        info->param_count = 0;
 146        if (info->parameters) {
 147                while (info->parameters[info->param_count]) {
 148                        info->param_count++;
 149                }
 150
 151                /* Warn on impossible argument count */
 152
 153                if (info->param_count > ACPI_METHOD_NUM_ARGS) {
 154                        ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
 155                                              ACPI_WARN_ALWAYS,
 156                                              "Excess arguments (%u) - using only %u",
 157                                              info->param_count,
 158                                              ACPI_METHOD_NUM_ARGS));
 159
 160                        info->param_count = ACPI_METHOD_NUM_ARGS;
 161                }
 162        }
 163
 164        /*
 165         * For predefined names: Check that the declared argument count
 166         * matches the ACPI spec -- otherwise this is a BIOS error.
 167         */
 168        acpi_ns_check_acpi_compliance(info->full_pathname, info->node,
 169                                      info->predefined);
 170
 171        /*
 172         * For all names: Check that the incoming argument count for
 173         * this method/object matches the actual ASL/AML definition.
 174         */
 175        acpi_ns_check_argument_count(info->full_pathname, info->node,
 176                                     info->param_count, info->predefined);
 177
 178        /* For predefined names: Typecheck all incoming arguments */
 179
 180        acpi_ns_check_argument_types(info);
 181
 182        /*
 183         * Three major evaluation cases:
 184         *
 185         * 1) Object types that cannot be evaluated by definition
 186         * 2) The object is a control method -- execute it
 187         * 3) The object is not a method -- just return it's current value
 188         */
 189        switch (acpi_ns_get_type(info->node)) {
 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                 * 1) Disallow evaluation of certain object types. For these,
 198                 *    object evaluation is undefined and not supported.
 199                 */
 200                ACPI_ERROR((AE_INFO,
 201                            "%s: Evaluation of object type [%s] is not supported",
 202                            info->full_pathname,
 203                            acpi_ut_get_type_name(info->node->type)));
 204
 205                status = AE_TYPE;
 206                goto cleanup;
 207
 208        case ACPI_TYPE_METHOD:
 209                /*
 210                 * 2) Object is a control method - execute it
 211                 */
 212
 213                /* Verify that there is a method object associated with this node */
 214
 215                if (!info->obj_desc) {
 216                        ACPI_ERROR((AE_INFO,
 217                                    "%s: Method has no attached sub-object",
 218                                    info->full_pathname));
 219                        status = AE_NULL_OBJECT;
 220                        goto cleanup;
 221                }
 222
 223                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 224                                  "**** Execute method [%s] at AML address %p length %X\n",
 225                                  info->full_pathname,
 226                                  info->obj_desc->method.aml_start + 1,
 227                                  info->obj_desc->method.aml_length - 1));
 228
 229                /*
 230                 * Any namespace deletion must acquire both the namespace and
 231                 * interpreter locks to ensure that no thread is using the portion of
 232                 * the namespace that is being deleted.
 233                 *
 234                 * Execute the method via the interpreter. The interpreter is locked
 235                 * here before calling into the AML parser
 236                 */
 237                acpi_ex_enter_interpreter();
 238                status = acpi_ps_execute_method(info);
 239                acpi_ex_exit_interpreter();
 240                break;
 241
 242        default:
 243                /*
 244                 * 3) All other non-method objects -- get the current object value
 245                 */
 246
 247                /*
 248                 * Some objects require additional resolution steps (e.g., the Node
 249                 * may be a field that must be read, etc.) -- we can't just grab
 250                 * the object out of the node.
 251                 *
 252                 * Use resolve_node_to_value() to get the associated value.
 253                 *
 254                 * NOTE: we can get away with passing in NULL for a walk state because
 255                 * the Node is guaranteed to not be a reference to either a method
 256                 * local or a method argument (because this interface is never called
 257                 * from a running method.)
 258                 *
 259                 * Even though we do not directly invoke the interpreter for object
 260                 * resolution, we must lock it because we could access an op_region.
 261                 * The op_region access code assumes that the interpreter is locked.
 262                 */
 263                acpi_ex_enter_interpreter();
 264
 265                /* TBD: resolve_node_to_value has a strange interface, fix */
 266
 267                info->return_object =
 268                    ACPI_CAST_PTR(union acpi_operand_object, info->node);
 269
 270                status =
 271                    acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
 272                                                  (struct acpi_namespace_node,
 273                                                   &info->return_object), NULL);
 274                acpi_ex_exit_interpreter();
 275
 276                if (ACPI_FAILURE(status)) {
 277                        goto cleanup;
 278                }
 279
 280                ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Returned object %p [%s]\n",
 281                                  info->return_object,
 282                                  acpi_ut_get_object_type_name(info->
 283                                                               return_object)));
 284
 285                status = AE_CTRL_RETURN_VALUE;  /* Always has a "return value" */
 286                break;
 287        }
 288
 289        /*
 290         * For predefined names, check the return value against the ACPI
 291         * specification. Some incorrect return value types are repaired.
 292         */
 293        (void)acpi_ns_check_return_value(info->node, info, info->param_count,
 294                                         status, &info->return_object);
 295
 296        /* Check if there is a return value that must be dealt with */
 297
 298        if (status == AE_CTRL_RETURN_VALUE) {
 299
 300                /* If caller does not want the return value, delete it */
 301
 302                if (info->flags & ACPI_IGNORE_RETURN_VALUE) {
 303                        acpi_ut_remove_reference(info->return_object);
 304                        info->return_object = NULL;
 305                }
 306
 307                /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
 308
 309                status = AE_OK;
 310        }
 311
 312        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 313                          "*** Completed evaluation of object %s ***\n",
 314                          info->relative_pathname));
 315
 316cleanup:
 317        /*
 318         * Namespace was unlocked by the handling acpi_ns* function, so we
 319         * just free the pathname and return
 320         */
 321        ACPI_FREE(info->full_pathname);
 322        info->full_pathname = NULL;
 323        return_ACPI_STATUS(status);
 324}
 325
 326/*******************************************************************************
 327 *
 328 * FUNCTION:    acpi_ns_exec_module_code_list
 329 *
 330 * PARAMETERS:  None
 331 *
 332 * RETURN:      None. Exceptions during method execution are ignored, since
 333 *              we cannot abort a table load.
 334 *
 335 * DESCRIPTION: Execute all elements of the global module-level code list.
 336 *              Each element is executed as a single control method.
 337 *
 338 ******************************************************************************/
 339
 340void acpi_ns_exec_module_code_list(void)
 341{
 342        union acpi_operand_object *prev;
 343        union acpi_operand_object *next;
 344        struct acpi_evaluate_info *info;
 345        u32 method_count = 0;
 346
 347        ACPI_FUNCTION_TRACE(ns_exec_module_code_list);
 348
 349        /* Exit now if the list is empty */
 350
 351        next = acpi_gbl_module_code_list;
 352        if (!next) {
 353                return_VOID;
 354        }
 355
 356        /* Allocate the evaluation information block */
 357
 358        info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info));
 359        if (!info) {
 360                return_VOID;
 361        }
 362
 363        /* Walk the list, executing each "method" */
 364
 365        while (next) {
 366                prev = next;
 367                next = next->method.mutex;
 368
 369                /* Clear the link field and execute the method */
 370
 371                prev->method.mutex = NULL;
 372                acpi_ns_exec_module_code(prev, info);
 373                method_count++;
 374
 375                /* Delete the (temporary) method object */
 376
 377                acpi_ut_remove_reference(prev);
 378        }
 379
 380        ACPI_INFO((AE_INFO,
 381                   "Executed %u blocks of module-level executable AML code",
 382                   method_count));
 383
 384        ACPI_FREE(info);
 385        acpi_gbl_module_code_list = NULL;
 386        return_VOID;
 387}
 388
 389/*******************************************************************************
 390 *
 391 * FUNCTION:    acpi_ns_exec_module_code
 392 *
 393 * PARAMETERS:  method_obj          - Object container for the module-level code
 394 *              info                - Info block for method evaluation
 395 *
 396 * RETURN:      None. Exceptions during method execution are ignored, since
 397 *              we cannot abort a table load.
 398 *
 399 * DESCRIPTION: Execute a control method containing a block of module-level
 400 *              executable AML code. The control method is temporarily
 401 *              installed to the root node, then evaluated.
 402 *
 403 ******************************************************************************/
 404
 405static void
 406acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
 407                         struct acpi_evaluate_info *info)
 408{
 409        union acpi_operand_object *parent_obj;
 410        struct acpi_namespace_node *parent_node;
 411        acpi_object_type type;
 412        acpi_status status;
 413
 414        ACPI_FUNCTION_TRACE(ns_exec_module_code);
 415
 416        /*
 417         * Get the parent node. We cheat by using the next_object field
 418         * of the method object descriptor.
 419         */
 420        parent_node = ACPI_CAST_PTR(struct acpi_namespace_node,
 421                                    method_obj->method.next_object);
 422        type = acpi_ns_get_type(parent_node);
 423
 424        /*
 425         * Get the region handler and save it in the method object. We may need
 426         * this if an operation region declaration causes a _REG method to be run.
 427         *
 428         * We can't do this in acpi_ps_link_module_code because
 429         * acpi_gbl_root_node->Object is NULL at PASS1.
 430         */
 431        if ((type == ACPI_TYPE_DEVICE) && parent_node->object) {
 432                method_obj->method.dispatch.handler =
 433                    parent_node->object->device.handler;
 434        }
 435
 436        /* Must clear next_object (acpi_ns_attach_object needs the field) */
 437
 438        method_obj->method.next_object = NULL;
 439
 440        /* Initialize the evaluation information block */
 441
 442        memset(info, 0, sizeof(struct acpi_evaluate_info));
 443        info->prefix_node = parent_node;
 444
 445        /*
 446         * Get the currently attached parent object. Add a reference, because the
 447         * ref count will be decreased when the method object is installed to
 448         * the parent node.
 449         */
 450        parent_obj = acpi_ns_get_attached_object(parent_node);
 451        if (parent_obj) {
 452                acpi_ut_add_reference(parent_obj);
 453        }
 454
 455        /* Install the method (module-level code) in the parent node */
 456
 457        status = acpi_ns_attach_object(parent_node, method_obj,
 458                                       ACPI_TYPE_METHOD);
 459        if (ACPI_FAILURE(status)) {
 460                goto exit;
 461        }
 462
 463        /* Execute the parent node as a control method */
 464
 465        status = acpi_ns_evaluate(info);
 466
 467        ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
 468                          method_obj->method.aml_start));
 469
 470        /* Delete a possible implicit return value (in slack mode) */
 471
 472        if (info->return_object) {
 473                acpi_ut_remove_reference(info->return_object);
 474        }
 475
 476        /* Detach the temporary method object */
 477
 478        acpi_ns_detach_object(parent_node);
 479
 480        /* Restore the original parent object */
 481
 482        if (parent_obj) {
 483                status = acpi_ns_attach_object(parent_node, parent_obj, type);
 484        } else {
 485                parent_node->type = (u8)type;
 486        }
 487
 488exit:
 489        if (parent_obj) {
 490                acpi_ut_remove_reference(parent_obj);
 491        }
 492        return_VOID;
 493}
 494