linux/drivers/acpi/acpica/psxface.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: psxface - Parser external interfaces
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2016, 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 "acdispat.h"
  48#include "acinterp.h"
  49#include "actables.h"
  50#include "acnamesp.h"
  51
  52#define _COMPONENT          ACPI_PARSER
  53ACPI_MODULE_NAME("psxface")
  54
  55/* Local Prototypes */
  56static void
  57acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
  58
  59/*******************************************************************************
  60 *
  61 * FUNCTION:    acpi_debug_trace
  62 *
  63 * PARAMETERS:  method_name     - Valid ACPI name string
  64 *              debug_level     - Optional level mask. 0 to use default
  65 *              debug_layer     - Optional layer mask. 0 to use default
  66 *              flags           - bit 1: one shot(1) or persistent(0)
  67 *
  68 * RETURN:      Status
  69 *
  70 * DESCRIPTION: External interface to enable debug tracing during control
  71 *              method execution
  72 *
  73 ******************************************************************************/
  74
  75acpi_status
  76acpi_debug_trace(const char *name, u32 debug_level, u32 debug_layer, u32 flags)
  77{
  78        acpi_status status;
  79
  80        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  81        if (ACPI_FAILURE(status)) {
  82                return (status);
  83        }
  84
  85        acpi_gbl_trace_method_name = name;
  86        acpi_gbl_trace_flags = flags;
  87        acpi_gbl_trace_dbg_level = debug_level;
  88        acpi_gbl_trace_dbg_layer = debug_layer;
  89        status = AE_OK;
  90
  91        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  92        return (status);
  93}
  94
  95/*******************************************************************************
  96 *
  97 * FUNCTION:    acpi_ps_execute_method
  98 *
  99 * PARAMETERS:  info            - Method info block, contains:
 100 *                  node            - Method Node to execute
 101 *                  obj_desc        - Method object
 102 *                  parameters      - List of parameters to pass to the method,
 103 *                                    terminated by NULL. Params itself may be
 104 *                                    NULL if no parameters are being passed.
 105 *                  return_object   - Where to put method's return value (if
 106 *                                    any). If NULL, no value is returned.
 107 *                  parameter_type  - Type of Parameter list
 108 *                  return_object   - Where to put method's return value (if
 109 *                                    any). If NULL, no value is returned.
 110 *                  pass_number     - Parse or execute pass
 111 *
 112 * RETURN:      Status
 113 *
 114 * DESCRIPTION: Execute a control method
 115 *
 116 ******************************************************************************/
 117
 118acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
 119{
 120        acpi_status status;
 121        union acpi_parse_object *op;
 122        struct acpi_walk_state *walk_state;
 123
 124        ACPI_FUNCTION_TRACE(ps_execute_method);
 125
 126        /* Quick validation of DSDT header */
 127
 128        acpi_tb_check_dsdt_header();
 129
 130        /* Validate the Info and method Node */
 131
 132        if (!info || !info->node) {
 133                return_ACPI_STATUS(AE_NULL_ENTRY);
 134        }
 135
 136        /* Init for new method, wait on concurrency semaphore */
 137
 138        status =
 139            acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
 140        if (ACPI_FAILURE(status)) {
 141                return_ACPI_STATUS(status);
 142        }
 143
 144        /*
 145         * The caller "owns" the parameters, so give each one an extra reference
 146         */
 147        acpi_ps_update_parameter_list(info, REF_INCREMENT);
 148
 149        /*
 150         * Execute the method. Performs parse simultaneously
 151         */
 152        ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
 153                          "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
 154                          info->node->name.ascii, info->node, info->obj_desc));
 155
 156        /* Create and init a Root Node */
 157
 158        op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
 159        if (!op) {
 160                status = AE_NO_MEMORY;
 161                goto cleanup;
 162        }
 163
 164        /* Create and initialize a new walk state */
 165
 166        info->pass_number = ACPI_IMODE_EXECUTE;
 167        walk_state =
 168            acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
 169                                      NULL, NULL);
 170        if (!walk_state) {
 171                status = AE_NO_MEMORY;
 172                goto cleanup;
 173        }
 174
 175        status = acpi_ds_init_aml_walk(walk_state, op, info->node,
 176                                       info->obj_desc->method.aml_start,
 177                                       info->obj_desc->method.aml_length, info,
 178                                       info->pass_number);
 179        if (ACPI_FAILURE(status)) {
 180                acpi_ds_delete_walk_state(walk_state);
 181                goto cleanup;
 182        }
 183
 184        if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
 185                walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
 186        }
 187
 188        /* Invoke an internal method if necessary */
 189
 190        if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
 191                status =
 192                    info->obj_desc->method.dispatch.implementation(walk_state);
 193                info->return_object = walk_state->return_desc;
 194
 195                /* Cleanup states */
 196
 197                acpi_ds_scope_stack_clear(walk_state);
 198                acpi_ps_cleanup_scope(&walk_state->parser_state);
 199                acpi_ds_terminate_control_method(walk_state->method_desc,
 200                                                 walk_state);
 201                acpi_ds_delete_walk_state(walk_state);
 202                goto cleanup;
 203        }
 204
 205        /*
 206         * Start method evaluation with an implicit return of zero.
 207         * This is done for Windows compatibility.
 208         */
 209        if (acpi_gbl_enable_interpreter_slack) {
 210                walk_state->implicit_return_obj =
 211                    acpi_ut_create_integer_object((u64) 0);
 212                if (!walk_state->implicit_return_obj) {
 213                        status = AE_NO_MEMORY;
 214                        acpi_ds_delete_walk_state(walk_state);
 215                        goto cleanup;
 216                }
 217        }
 218
 219        /* Parse the AML */
 220
 221        status = acpi_ps_parse_aml(walk_state);
 222
 223        /* walk_state was deleted by parse_aml */
 224
 225cleanup:
 226        acpi_ps_delete_parse_tree(op);
 227
 228        /* Take away the extra reference that we gave the parameters above */
 229
 230        acpi_ps_update_parameter_list(info, REF_DECREMENT);
 231
 232        /* Exit now if error above */
 233
 234        if (ACPI_FAILURE(status)) {
 235                return_ACPI_STATUS(status);
 236        }
 237
 238        /*
 239         * If the method has returned an object, signal this to the caller with
 240         * a control exception code
 241         */
 242        if (info->return_object) {
 243                ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
 244                                  info->return_object));
 245                ACPI_DUMP_STACK_ENTRY(info->return_object);
 246
 247                status = AE_CTRL_RETURN_VALUE;
 248        }
 249
 250        return_ACPI_STATUS(status);
 251}
 252
 253/*******************************************************************************
 254 *
 255 * FUNCTION:    acpi_ps_execute_table
 256 *
 257 * PARAMETERS:  info            - Method info block, contains:
 258 *              node            - Node to where the is entered into the
 259 *                                namespace
 260 *              obj_desc        - Pseudo method object describing the AML
 261 *                                code of the entire table
 262 *              pass_number     - Parse or execute pass
 263 *
 264 * RETURN:      Status
 265 *
 266 * DESCRIPTION: Execute a table
 267 *
 268 ******************************************************************************/
 269
 270acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
 271{
 272        acpi_status status;
 273        union acpi_parse_object *op = NULL;
 274        struct acpi_walk_state *walk_state = NULL;
 275
 276        ACPI_FUNCTION_TRACE(ps_execute_table);
 277
 278        /* Create and init a Root Node */
 279
 280        op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
 281        if (!op) {
 282                status = AE_NO_MEMORY;
 283                goto cleanup;
 284        }
 285
 286        /* Create and initialize a new walk state */
 287
 288        walk_state =
 289            acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
 290                                      NULL, NULL);
 291        if (!walk_state) {
 292                status = AE_NO_MEMORY;
 293                goto cleanup;
 294        }
 295
 296        status = acpi_ds_init_aml_walk(walk_state, op, info->node,
 297                                       info->obj_desc->method.aml_start,
 298                                       info->obj_desc->method.aml_length, info,
 299                                       info->pass_number);
 300        if (ACPI_FAILURE(status)) {
 301                goto cleanup;
 302        }
 303
 304        if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
 305                walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
 306        }
 307
 308        /* Info->Node is the default location to load the table  */
 309
 310        if (info->node && info->node != acpi_gbl_root_node) {
 311                status =
 312                    acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD,
 313                                             walk_state);
 314                if (ACPI_FAILURE(status)) {
 315                        goto cleanup;
 316                }
 317        }
 318
 319        /*
 320         * Parse the AML, walk_state will be deleted by parse_aml
 321         */
 322        acpi_ex_enter_interpreter();
 323        status = acpi_ps_parse_aml(walk_state);
 324        acpi_ex_exit_interpreter();
 325        walk_state = NULL;
 326
 327cleanup:
 328        if (walk_state) {
 329                acpi_ds_delete_walk_state(walk_state);
 330        }
 331        if (op) {
 332                acpi_ps_delete_parse_tree(op);
 333        }
 334        return_ACPI_STATUS(status);
 335}
 336
 337/*******************************************************************************
 338 *
 339 * FUNCTION:    acpi_ps_update_parameter_list
 340 *
 341 * PARAMETERS:  info            - See struct acpi_evaluate_info
 342 *                                (Used: parameter_type and Parameters)
 343 *              action          - Add or Remove reference
 344 *
 345 * RETURN:      Status
 346 *
 347 * DESCRIPTION: Update reference count on all method parameter objects
 348 *
 349 ******************************************************************************/
 350
 351static void
 352acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
 353{
 354        u32 i;
 355
 356        if (info->parameters) {
 357
 358                /* Update reference count for each parameter */
 359
 360                for (i = 0; info->parameters[i]; i++) {
 361
 362                        /* Ignore errors, just do them all */
 363
 364                        (void)acpi_ut_update_object_reference(info->
 365                                                              parameters[i],
 366                                                              action);
 367                }
 368        }
 369}
 370