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