psxface.c 11.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/******************************************************************************
 *
 * Module Name: psxface - Parser external interfaces
 *
 *****************************************************************************/

/*
8
 * Copyright (C) 2000 - 2011, Intel Corp.
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
L
Len Brown 已提交
45 46 47 48
#include "accommon.h"
#include "acparser.h"
#include "acdispat.h"
#include "acinterp.h"
49
#include "actables.h"
L
Linus Torvalds 已提交
50 51

#define _COMPONENT          ACPI_PARSER
L
Len Brown 已提交
52
ACPI_MODULE_NAME("psxface")
L
Linus Torvalds 已提交
53

54
/* Local Prototypes */
B
Bob Moore 已提交
55
static void acpi_ps_start_trace(struct acpi_evaluate_info *info);
B
Bob Moore 已提交
56

B
Bob Moore 已提交
57
static void acpi_ps_stop_trace(struct acpi_evaluate_info *info);
B
Bob Moore 已提交
58

59
static void
B
Bob Moore 已提交
60
acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action);
L
Linus Torvalds 已提交
61

B
Bob Moore 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/*******************************************************************************
 *
 * FUNCTION:    acpi_debug_trace
 *
 * PARAMETERS:  method_name     - Valid ACPI name string
 *              debug_level     - Optional level mask. 0 to use default
 *              debug_layer     - Optional layer mask. 0 to use default
 *              Flags           - bit 1: one shot(1) or persistent(0)
 *
 * RETURN:      Status
 *
 * DESCRIPTION: External interface to enable debug tracing during control
 *              method execution
 *
 ******************************************************************************/

acpi_status
acpi_debug_trace(char *name, u32 debug_level, u32 debug_layer, u32 flags)
{
	acpi_status status;

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return (status);
	}

	/* TBDs: Validate name, allow full path or just nameseg */

B
Bob Moore 已提交
90
	acpi_gbl_trace_method_name = *ACPI_CAST_PTR(u32, name);
B
Bob Moore 已提交
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
	acpi_gbl_trace_flags = flags;

	if (debug_level) {
		acpi_gbl_trace_dbg_level = debug_level;
	}
	if (debug_layer) {
		acpi_gbl_trace_dbg_layer = debug_layer;
	}

	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
	return (AE_OK);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ps_start_trace
 *
 * PARAMETERS:  Info        - Method info struct
 *
 * RETURN:      None
 *
 * DESCRIPTION: Start control method execution trace
 *
 ******************************************************************************/

B
Bob Moore 已提交
116
static void acpi_ps_start_trace(struct acpi_evaluate_info *info)
B
Bob Moore 已提交
117 118 119 120 121 122 123 124 125 126 127
{
	acpi_status status;

	ACPI_FUNCTION_ENTRY();

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return;
	}

	if ((!acpi_gbl_trace_method_name) ||
B
Bob Moore 已提交
128
	    (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
B
Bob Moore 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
		goto exit;
	}

	acpi_gbl_original_dbg_level = acpi_dbg_level;
	acpi_gbl_original_dbg_layer = acpi_dbg_layer;

	acpi_dbg_level = 0x00FFFFFF;
	acpi_dbg_layer = ACPI_UINT32_MAX;

	if (acpi_gbl_trace_dbg_level) {
		acpi_dbg_level = acpi_gbl_trace_dbg_level;
	}
	if (acpi_gbl_trace_dbg_layer) {
		acpi_dbg_layer = acpi_gbl_trace_dbg_layer;
	}

      exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ps_stop_trace
 *
 * PARAMETERS:  Info        - Method info struct
 *
 * RETURN:      None
 *
 * DESCRIPTION: Stop control method execution trace
 *
 ******************************************************************************/

B
Bob Moore 已提交
161
static void acpi_ps_stop_trace(struct acpi_evaluate_info *info)
B
Bob Moore 已提交
162 163 164 165 166 167 168 169 170 171 172
{
	acpi_status status;

	ACPI_FUNCTION_ENTRY();

	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE(status)) {
		return;
	}

	if ((!acpi_gbl_trace_method_name) ||
B
Bob Moore 已提交
173
	    (acpi_gbl_trace_method_name != info->resolved_node->name.integer)) {
B
Bob Moore 已提交
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
		goto exit;
	}

	/* Disable further tracing if type is one-shot */

	if (acpi_gbl_trace_flags & 1) {
		acpi_gbl_trace_method_name = 0;
		acpi_gbl_trace_dbg_level = 0;
		acpi_gbl_trace_dbg_layer = 0;
	}

	acpi_dbg_level = acpi_gbl_original_dbg_level;
	acpi_dbg_layer = acpi_gbl_original_dbg_layer;

      exit:
	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
}

L
Linus Torvalds 已提交
192 193
/*******************************************************************************
 *
194
 * FUNCTION:    acpi_ps_execute_method
L
Linus Torvalds 已提交
195
 *
R
Robert Moore 已提交
196 197
 * PARAMETERS:  Info            - Method info block, contains:
 *                  Node            - Method Node to execute
198
 *                  obj_desc        - Method object
R
Robert Moore 已提交
199
 *                  Parameters      - List of parameters to pass to the method,
L
Linus Torvalds 已提交
200 201
 *                                    terminated by NULL. Params itself may be
 *                                    NULL if no parameters are being passed.
R
Robert Moore 已提交
202 203 204 205 206
 *                  return_object   - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
 *                  parameter_type  - Type of Parameter list
 *                  return_object   - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
207
 *                  pass_number     - Parse or execute pass
L
Linus Torvalds 已提交
208 209 210 211 212 213 214
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Execute a control method
 *
 ******************************************************************************/

B
Bob Moore 已提交
215
acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
L
Linus Torvalds 已提交
216
{
L
Len Brown 已提交
217
	acpi_status status;
218 219
	union acpi_parse_object *op;
	struct acpi_walk_state *walk_state;
L
Linus Torvalds 已提交
220

B
Bob Moore 已提交
221
	ACPI_FUNCTION_TRACE(ps_execute_method);
L
Linus Torvalds 已提交
222

223 224 225 226
	/* Quick validation of DSDT header */

	acpi_tb_check_dsdt_header();

227
	/* Validate the Info and method Node */
L
Linus Torvalds 已提交
228

B
Bob Moore 已提交
229
	if (!info || !info->resolved_node) {
L
Len Brown 已提交
230
		return_ACPI_STATUS(AE_NULL_ENTRY);
L
Linus Torvalds 已提交
231 232 233 234
	}

	/* Init for new method, wait on concurrency semaphore */

L
Len Brown 已提交
235
	status =
B
Bob Moore 已提交
236 237
	    acpi_ds_begin_method_execution(info->resolved_node, info->obj_desc,
					   NULL);
L
Len Brown 已提交
238 239
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
240 241
	}

242
	/*
243
	 * The caller "owns" the parameters, so give each one an extra reference
244
	 */
L
Len Brown 已提交
245
	acpi_ps_update_parameter_list(info, REF_INCREMENT);
L
Linus Torvalds 已提交
246

B
Bob Moore 已提交
247 248 249 250
	/* Begin tracing if requested */

	acpi_ps_start_trace(info);

251
	/*
252
	 * Execute the method. Performs parse simultaneously
253
	 */
L
Len Brown 已提交
254
	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
255 256 257
			  "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
			  info->resolved_node->name.ascii, info->resolved_node,
			  info->obj_desc));
L
Linus Torvalds 已提交
258

259 260 261 262 263
	/* Create and init a Root Node */

	op = acpi_ps_create_scope_op();
	if (!op) {
		status = AE_NO_MEMORY;
264
		goto cleanup;
L
Linus Torvalds 已提交
265 266
	}

267
	/* Create and initialize a new walk state */
L
Linus Torvalds 已提交
268

269
	info->pass_number = ACPI_IMODE_EXECUTE;
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
	walk_state =
	    acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL,
				      NULL, NULL);
	if (!walk_state) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	status = acpi_ds_init_aml_walk(walk_state, op, info->resolved_node,
				       info->obj_desc->method.aml_start,
				       info->obj_desc->method.aml_length, info,
				       info->pass_number);
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
		goto cleanup;
	}

287
	if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) {
288 289 290
		walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
	}

291 292
	/* Invoke an internal method if necessary */

293
	if (info->obj_desc->method.info_flags & ACPI_METHOD_INTERNAL_ONLY) {
294
		status =
295
		    info->obj_desc->method.dispatch.implementation(walk_state);
296 297 298 299 300 301 302 303 304 305 306 307
		info->return_object = walk_state->return_desc;

		/* Cleanup states */

		acpi_ds_scope_stack_clear(walk_state);
		acpi_ps_cleanup_scope(&walk_state->parser_state);
		acpi_ds_terminate_control_method(walk_state->method_desc,
						 walk_state);
		acpi_ds_delete_walk_state(walk_state);
		goto cleanup;
	}

308 309 310 311 312 313
	/*
	 * Start method evaluation with an implicit return of zero.
	 * This is done for Windows compatibility.
	 */
	if (acpi_gbl_enable_interpreter_slack) {
		walk_state->implicit_return_obj =
314
		    acpi_ut_create_integer_object((u64) 0);
315 316 317 318 319 320 321
		if (!walk_state->implicit_return_obj) {
			status = AE_NO_MEMORY;
			acpi_ds_delete_walk_state(walk_state);
			goto cleanup;
		}
	}

322 323 324 325 326
	/* Parse the AML */

	status = acpi_ps_parse_aml(walk_state);

	/* walk_state was deleted by parse_aml */
327

L
Len Brown 已提交
328
      cleanup:
329 330
	acpi_ps_delete_parse_tree(op);

B
Bob Moore 已提交
331 332 333 334
	/* End optional tracing */

	acpi_ps_stop_trace(info);

335
	/* Take away the extra reference that we gave the parameters above */
L
Linus Torvalds 已提交
336

L
Len Brown 已提交
337
	acpi_ps_update_parameter_list(info, REF_DECREMENT);
L
Linus Torvalds 已提交
338

339
	/* Exit now if error above */
L
Linus Torvalds 已提交
340

L
Len Brown 已提交
341 342
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
343 344
	}

345 346 347 348 349
	/*
	 * If the method has returned an object, signal this to the caller with
	 * a control exception code
	 */
	if (info->return_object) {
B
Bob Moore 已提交
350
		ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
L
Len Brown 已提交
351 352
				  info->return_object));
		ACPI_DUMP_STACK_ENTRY(info->return_object);
353 354

		status = AE_CTRL_RETURN_VALUE;
L
Linus Torvalds 已提交
355 356
	}

L
Len Brown 已提交
357
	return_ACPI_STATUS(status);
358
}
R
Robert Moore 已提交
359

360 361 362 363
/*******************************************************************************
 *
 * FUNCTION:    acpi_ps_update_parameter_list
 *
B
Bob Moore 已提交
364
 * PARAMETERS:  Info            - See struct acpi_evaluate_info
365 366 367 368 369 370 371 372
 *                                (Used: parameter_type and Parameters)
 *              Action          - Add or Remove reference
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Update reference count on all method parameter objects
 *
 ******************************************************************************/
L
Linus Torvalds 已提交
373

374
static void
B
Bob Moore 已提交
375
acpi_ps_update_parameter_list(struct acpi_evaluate_info *info, u16 action)
376
{
377
	u32 i;
L
Linus Torvalds 已提交
378

379
	if (info->parameters) {
B
Bob Moore 已提交
380

381
		/* Update reference count for each parameter */
L
Linus Torvalds 已提交
382 383

		for (i = 0; info->parameters[i]; i++) {
B
Bob Moore 已提交
384

L
Linus Torvalds 已提交
385 386
			/* Ignore errors, just do them all */

L
Len Brown 已提交
387 388 389
			(void)acpi_ut_update_object_reference(info->
							      parameters[i],
							      action);
L
Linus Torvalds 已提交
390 391
		}
	}
392
}