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