1 /****************************************************************************** 2 * 3 * Module Name: psxface - Parser external interfaces 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2018, 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 53 ACPI_MODULE_NAME("psxface") 54 55 /* Local Prototypes */ 56 static void 57 acpi_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 75 acpi_status 76 acpi_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 118 acpi_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 225 cleanup: 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 270 acpi_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 327 cleanup: 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 351 static void 352 acpi_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