Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: psxface - Parser external interfaces
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acparser.h"
0013 #include "acdispat.h"
0014 #include "acinterp.h"
0015 #include "actables.h"
0016 #include "acnamesp.h"
0017 
0018 #define _COMPONENT          ACPI_PARSER
0019 ACPI_MODULE_NAME("psxface")
0020 
0021 /* Local Prototypes */
0022 static void
0023 acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
0024 
0025 /*******************************************************************************
0026  *
0027  * FUNCTION:    acpi_debug_trace
0028  *
0029  * PARAMETERS:  method_name     - Valid ACPI name string
0030  *              debug_level     - Optional level mask. 0 to use default
0031  *              debug_layer     - Optional layer mask. 0 to use default
0032  *              flags           - bit 1: one shot(1) or persistent(0)
0033  *
0034  * RETURN:      Status
0035  *
0036  * DESCRIPTION: External interface to enable debug tracing during control
0037  *              method execution
0038  *
0039  ******************************************************************************/
0040 
0041 acpi_status
0042 acpi_debug_trace(const char *name, u32 debug_level, u32 debug_layer, u32 flags)
0043 {
0044     acpi_status status;
0045 
0046     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0047     if (ACPI_FAILURE(status)) {
0048         return (status);
0049     }
0050 
0051     acpi_gbl_trace_method_name = name;
0052     acpi_gbl_trace_flags = flags;
0053     acpi_gbl_trace_dbg_level = debug_level;
0054     acpi_gbl_trace_dbg_layer = debug_layer;
0055     status = AE_OK;
0056 
0057     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0058     return (status);
0059 }
0060 
0061 /*******************************************************************************
0062  *
0063  * FUNCTION:    acpi_ps_execute_method
0064  *
0065  * PARAMETERS:  info            - Method info block, contains:
0066  *                  node            - Method Node to execute
0067  *                  obj_desc        - Method object
0068  *                  parameters      - List of parameters to pass to the method,
0069  *                                    terminated by NULL. Params itself may be
0070  *                                    NULL if no parameters are being passed.
0071  *                  return_object   - Where to put method's return value (if
0072  *                                    any). If NULL, no value is returned.
0073  *                  parameter_type  - Type of Parameter list
0074  *                  return_object   - Where to put method's return value (if
0075  *                                    any). If NULL, no value is returned.
0076  *                  pass_number     - Parse or execute pass
0077  *
0078  * RETURN:      Status
0079  *
0080  * DESCRIPTION: Execute a control method
0081  *
0082  ******************************************************************************/
0083 
0084 acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
0085 {
0086     acpi_status status;
0087     union acpi_parse_object *op;
0088     struct acpi_walk_state *walk_state;
0089 
0090     ACPI_FUNCTION_TRACE(ps_execute_method);
0091 
0092     /* Quick validation of DSDT header */
0093 
0094     acpi_tb_check_dsdt_header();
0095 
0096     /* Validate the Info and method Node */
0097 
0098     if (!info || !info->node) {
0099         return_ACPI_STATUS(AE_NULL_ENTRY);
0100     }
0101 
0102     /* Init for new method, wait on concurrency semaphore */
0103 
0104     status =
0105         acpi_ds_begin_method_execution(info->node, info->obj_desc, NULL);
0106     if (ACPI_FAILURE(status)) {
0107         return_ACPI_STATUS(status);
0108     }
0109 
0110     /*
0111      * The caller "owns" the parameters, so give each one an extra reference
0112      */
0113     acpi_ps_update_parameter_list(info, REF_INCREMENT);
0114 
0115     /*
0116      * Execute the method. Performs parse simultaneously
0117      */
0118     ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
0119               "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
0120               info->node->name.ascii, info->node, info->obj_desc));
0121 
0122     /* Create and init a Root Node */
0123 
0124     op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
0125     if (!op) {
0126         status = AE_NO_MEMORY;
0127         goto cleanup;
0128     }
0129 
0130     /* Create and initialize a new walk state */
0131 
0132     info->pass_number = ACPI_IMODE_EXECUTE;
0133     walk_state =
0134         acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
0135                       NULL, NULL);
0136     if (!walk_state) {
0137         status = AE_NO_MEMORY;
0138         goto cleanup;
0139     }
0140 
0141     status = acpi_ds_init_aml_walk(walk_state, op, info->node,
0142                        info->obj_desc->method.aml_start,
0143                        info->obj_desc->method.aml_length, info,
0144                        info->pass_number);
0145     if (ACPI_FAILURE(status)) {
0146         acpi_ds_delete_walk_state(walk_state);
0147         goto cleanup;
0148     }
0149 
0150     walk_state->method_pathname = info->full_pathname;
0151     walk_state->method_is_nested = FALSE;
0152 
0153     if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
0154         walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
0155     }
0156 
0157     /* Invoke an internal method if necessary */
0158 
0159     if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
0160         status =
0161             info->obj_desc->method.dispatch.implementation(walk_state);
0162         info->return_object = walk_state->return_desc;
0163 
0164         /* Cleanup states */
0165 
0166         acpi_ds_scope_stack_clear(walk_state);
0167         acpi_ps_cleanup_scope(&walk_state->parser_state);
0168         acpi_ds_terminate_control_method(walk_state->method_desc,
0169                          walk_state);
0170         acpi_ds_delete_walk_state(walk_state);
0171         goto cleanup;
0172     }
0173 
0174     /*
0175      * Start method evaluation with an implicit return of zero.
0176      * This is done for Windows compatibility.
0177      */
0178     if (acpi_gbl_enable_interpreter_slack) {
0179         walk_state->implicit_return_obj =
0180             acpi_ut_create_integer_object((u64) 0);
0181         if (!walk_state->implicit_return_obj) {
0182             status = AE_NO_MEMORY;
0183             acpi_ds_delete_walk_state(walk_state);
0184             goto cleanup;
0185         }
0186     }
0187 
0188     /* Parse the AML */
0189 
0190     status = acpi_ps_parse_aml(walk_state);
0191 
0192     /* walk_state was deleted by parse_aml */
0193 
0194 cleanup:
0195     acpi_ps_delete_parse_tree(op);
0196 
0197     /* Take away the extra reference that we gave the parameters above */
0198 
0199     acpi_ps_update_parameter_list(info, REF_DECREMENT);
0200 
0201     /* Exit now if error above */
0202 
0203     if (ACPI_FAILURE(status)) {
0204         return_ACPI_STATUS(status);
0205     }
0206 
0207     /*
0208      * If the method has returned an object, signal this to the caller with
0209      * a control exception code
0210      */
0211     if (info->return_object) {
0212         ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
0213                   info->return_object));
0214         ACPI_DUMP_STACK_ENTRY(info->return_object);
0215 
0216         status = AE_CTRL_RETURN_VALUE;
0217     }
0218 
0219     return_ACPI_STATUS(status);
0220 }
0221 
0222 /*******************************************************************************
0223  *
0224  * FUNCTION:    acpi_ps_execute_table
0225  *
0226  * PARAMETERS:  info            - Method info block, contains:
0227  *              node            - Node to where the is entered into the
0228  *                                namespace
0229  *              obj_desc        - Pseudo method object describing the AML
0230  *                                code of the entire table
0231  *              pass_number     - Parse or execute pass
0232  *
0233  * RETURN:      Status
0234  *
0235  * DESCRIPTION: Execute a table
0236  *
0237  ******************************************************************************/
0238 
0239 acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info)
0240 {
0241     acpi_status status;
0242     union acpi_parse_object *op = NULL;
0243     struct acpi_walk_state *walk_state = NULL;
0244 
0245     ACPI_FUNCTION_TRACE(ps_execute_table);
0246 
0247     /* Create and init a Root Node */
0248 
0249     op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start);
0250     if (!op) {
0251         status = AE_NO_MEMORY;
0252         goto cleanup;
0253     }
0254 
0255     /* Create and initialize a new walk state */
0256 
0257     walk_state =
0258         acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
0259                       NULL, NULL);
0260     if (!walk_state) {
0261         status = AE_NO_MEMORY;
0262         goto cleanup;
0263     }
0264 
0265     status = acpi_ds_init_aml_walk(walk_state, op, info->node,
0266                        info->obj_desc->method.aml_start,
0267                        info->obj_desc->method.aml_length, info,
0268                        info->pass_number);
0269     if (ACPI_FAILURE(status)) {
0270         goto cleanup;
0271     }
0272 
0273     walk_state->method_pathname = info->full_pathname;
0274     walk_state->method_is_nested = FALSE;
0275 
0276     if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
0277         walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
0278     }
0279 
0280     /* Info->Node is the default location to load the table  */
0281 
0282     if (info->node && info->node != acpi_gbl_root_node) {
0283         status =
0284             acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD,
0285                          walk_state);
0286         if (ACPI_FAILURE(status)) {
0287             goto cleanup;
0288         }
0289     }
0290 
0291     /*
0292      * Parse the AML, walk_state will be deleted by parse_aml
0293      */
0294     acpi_ex_enter_interpreter();
0295     status = acpi_ps_parse_aml(walk_state);
0296     acpi_ex_exit_interpreter();
0297     walk_state = NULL;
0298 
0299 cleanup:
0300     if (walk_state) {
0301         acpi_ds_delete_walk_state(walk_state);
0302     }
0303     if (op) {
0304         acpi_ps_delete_parse_tree(op);
0305     }
0306     return_ACPI_STATUS(status);
0307 }
0308 
0309 /*******************************************************************************
0310  *
0311  * FUNCTION:    acpi_ps_update_parameter_list
0312  *
0313  * PARAMETERS:  info            - See struct acpi_evaluate_info
0314  *                                (Used: parameter_type and Parameters)
0315  *              action          - Add or Remove reference
0316  *
0317  * RETURN:      Status
0318  *
0319  * DESCRIPTION: Update reference count on all method parameter objects
0320  *
0321  ******************************************************************************/
0322 
0323 static void
0324 acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
0325 {
0326     u32 i;
0327 
0328     if (info->parameters) {
0329 
0330         /* Update reference count for each parameter */
0331 
0332         for (i = 0; info->parameters[i]; i++) {
0333 
0334             /* Ignore errors, just do them all */
0335 
0336             (void)acpi_ut_update_object_reference(info->
0337                                   parameters[i],
0338                                   action);
0339         }
0340     }
0341 }