342 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: psxface - Parser external interfaces5 *6 * Copyright (C) 2000 - 2023, 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_PARSER19ACPI_MODULE_NAME("psxface")20 21/* Local Prototypes */22static void23acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);24 25/*******************************************************************************26 *27 * FUNCTION: acpi_debug_trace28 *29 * PARAMETERS: method_name - Valid ACPI name string30 * debug_level - Optional level mask. 0 to use default31 * debug_layer - Optional layer mask. 0 to use default32 * flags - bit 1: one shot(1) or persistent(0)33 *34 * RETURN: Status35 *36 * DESCRIPTION: External interface to enable debug tracing during control37 * method execution38 *39 ******************************************************************************/40 41acpi_status42acpi_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_method64 *65 * PARAMETERS: info - Method info block, contains:66 * node - Method Node to execute67 * obj_desc - Method object68 * parameters - List of parameters to pass to the method,69 * terminated by NULL. Params itself may be70 * NULL if no parameters are being passed.71 * return_object - Where to put method's return value (if72 * any). If NULL, no value is returned.73 * parameter_type - Type of Parameter list74 * return_object - Where to put method's return value (if75 * any). If NULL, no value is returned.76 * pass_number - Parse or execute pass77 *78 * RETURN: Status79 *80 * DESCRIPTION: Execute a control method81 *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 reference112 */113 acpi_ps_update_parameter_list(info, REF_INCREMENT);114 115 /*116 * Execute the method. Performs parse simultaneously117 */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 with209 * a control exception code210 */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_table225 *226 * PARAMETERS: info - Method info block, contains:227 * node - Node to where the is entered into the228 * namespace229 * obj_desc - Pseudo method object describing the AML230 * code of the entire table231 * pass_number - Parse or execute pass232 *233 * RETURN: Status234 *235 * DESCRIPTION: Execute a table236 *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_aml293 */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_list312 *313 * PARAMETERS: info - See struct acpi_evaluate_info314 * (Used: parameter_type and Parameters)315 * action - Add or Remove reference316 *317 * RETURN: Status318 *319 * DESCRIPTION: Update reference count on all method parameter objects320 *321 ******************************************************************************/322 323static void324acpi_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