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