1 /****************************************************************************** 2 * 3 * Module Name: psxface - Parser external interfaces 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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->resolved_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->resolved_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->resolved_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->resolved_node, info->obj_desc, 237 NULL); 238 if (ACPI_FAILURE(status)) { 239 return_ACPI_STATUS(status); 240 } 241 242 /* 243 * The caller "owns" the parameters, so give each one an extra reference 244 */ 245 acpi_ps_update_parameter_list(info, REF_INCREMENT); 246 247 /* Begin tracing if requested */ 248 249 acpi_ps_start_trace(info); 250 251 /* 252 * Execute the method. Performs parse simultaneously 253 */ 254 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 255 "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", 256 info->resolved_node->name.ascii, info->resolved_node, 257 info->obj_desc)); 258 259 /* Create and init a Root Node */ 260 261 op = acpi_ps_create_scope_op(); 262 if (!op) { 263 status = AE_NO_MEMORY; 264 goto cleanup; 265 } 266 267 /* Create and initialize a new walk state */ 268 269 info->pass_number = ACPI_IMODE_EXECUTE; 270 walk_state = 271 acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, 272 NULL, NULL); 273 if (!walk_state) { 274 status = AE_NO_MEMORY; 275 goto cleanup; 276 } 277 278 status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node, 279 info->obj_desc->method.aml_start, 280 info->obj_desc->method.aml_length, info, 281 info->pass_number); 282 if (ACPI_FAILURE(status)) { 283 acpi_ds_delete_walk_state(walk_state); 284 goto cleanup; 285 } 286 287 if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) { 288 walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL; 289 } 290 291 /* Invoke an internal method if necessary */ 292 293 if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) { 294 status = 295 info->obj_desc->method.dispatch.implementation(walk_state); 296 info->return_object = walk_state->return_desc; 297 298 /* Cleanup states */ 299 300 acpi_ds_scope_stack_clear(walk_state); 301 acpi_ps_cleanup_scope(&walk_state->parser_state); 302 acpi_ds_terminate_control_method(walk_state->method_desc, 303 walk_state); 304 acpi_ds_delete_walk_state(walk_state); 305 goto cleanup; 306 } 307 308 /* 309 * Start method evaluation with an implicit return of zero. 310 * This is done for Windows compatibility. 311 */ 312 if (acpi_gbl_enable_interpreter_slack) { 313 walk_state->implicit_return_obj = 314 acpi_ut_create_integer_object((u64) 0); 315 if (!walk_state->implicit_return_obj) { 316 status = AE_NO_MEMORY; 317 acpi_ds_delete_walk_state(walk_state); 318 goto cleanup; 319 } 320 } 321 322 /* Parse the AML */ 323 324 status = acpi_ps_parse_aml(walk_state); 325 326 /* walk_state was deleted by parse_aml */ 327 328 cleanup: 329 acpi_ps_delete_parse_tree(op); 330 331 /* End optional tracing */ 332 333 acpi_ps_stop_trace(info); 334 335 /* Take away the extra reference that we gave the parameters above */ 336 337 acpi_ps_update_parameter_list(info, REF_DECREMENT); 338 339 /* Exit now if error above */ 340 341 if (ACPI_FAILURE(status)) { 342 return_ACPI_STATUS(status); 343 } 344 345 /* 346 * If the method has returned an object, signal this to the caller with 347 * a control exception code 348 */ 349 if (info->return_object) { 350 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", 351 info->return_object)); 352 ACPI_DUMP_STACK_ENTRY(info->return_object); 353 354 status = AE_CTRL_RETURN_VALUE; 355 } 356 357 return_ACPI_STATUS(status); 358 } 359 360 /******************************************************************************* 361 * 362 * FUNCTION: acpi_ps_update_parameter_list 363 * 364 * PARAMETERS: info - See struct acpi_evaluate_info 365 * (Used: parameter_type and Parameters) 366 * action - Add or Remove reference 367 * 368 * RETURN: Status 369 * 370 * DESCRIPTION: Update reference count on all method parameter objects 371 * 372 ******************************************************************************/ 373 374 static void 375 acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action) 376 { 377 u32 i; 378 379 if (info->parameters) { 380 381 /* Update reference count for each parameter */ 382 383 for (i = 0; info->parameters[i]; i++) { 384 385 /* Ignore errors, just do them all */ 386 387 (void)acpi_ut_update_object_reference(info-> 388 parameters[i], 389 action); 390 } 391 } 392 } 393