dsopcode.c 39.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/******************************************************************************
 *
 * Module Name: dsopcode - Dispatcher Op Region support and handling of
 *                         "control" opcodes
 *
 *****************************************************************************/

/*
9
 * Copyright (C) 2000 - 2011, Intel Corp.
L
Linus Torvalds 已提交
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 45
 * 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 已提交
46 47 48 49 50 51 52 53
#include "accommon.h"
#include "acparser.h"
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
#include "acnamesp.h"
#include "acevents.h"
#include "actables.h"
L
Linus Torvalds 已提交
54 55

#define _COMPONENT          ACPI_DISPATCHER
L
Len Brown 已提交
56
ACPI_MODULE_NAME("dsopcode")
L
Linus Torvalds 已提交
57

R
Robert Moore 已提交
58 59
/* Local prototypes */
static acpi_status
L
Len Brown 已提交
60 61 62
acpi_ds_execute_arguments(struct acpi_namespace_node *node,
			  struct acpi_namespace_node *scope_node,
			  u32 aml_length, u8 * aml_start);
R
Robert Moore 已提交
63 64

static acpi_status
L
Len Brown 已提交
65 66 67 68 69 70
acpi_ds_init_buffer_field(u16 aml_opcode,
			  union acpi_operand_object *obj_desc,
			  union acpi_operand_object *buffer_desc,
			  union acpi_operand_object *offset_desc,
			  union acpi_operand_object *length_desc,
			  union acpi_operand_object *result_desc);
R
Robert Moore 已提交
71 72

/*******************************************************************************
L
Linus Torvalds 已提交
73 74 75
 *
 * FUNCTION:    acpi_ds_execute_arguments
 *
R
Robert Moore 已提交
76 77
 * PARAMETERS:  Node                - Object NS node
 *              scope_node          - Parent NS node
L
Linus Torvalds 已提交
78 79 80 81 82 83 84
 *              aml_length          - Length of executable AML
 *              aml_start           - Pointer to the AML
 *
 * RETURN:      Status.
 *
 * DESCRIPTION: Late (deferred) execution of region or field arguments
 *
R
Robert Moore 已提交
85
 ******************************************************************************/
L
Linus Torvalds 已提交
86

R
Robert Moore 已提交
87
static acpi_status
L
Len Brown 已提交
88 89 90
acpi_ds_execute_arguments(struct acpi_namespace_node *node,
			  struct acpi_namespace_node *scope_node,
			  u32 aml_length, u8 * aml_start)
L
Linus Torvalds 已提交
91
{
L
Len Brown 已提交
92 93 94
	acpi_status status;
	union acpi_parse_object *op;
	struct acpi_walk_state *walk_state;
L
Linus Torvalds 已提交
95

B
Bob Moore 已提交
96
	ACPI_FUNCTION_TRACE(ds_execute_arguments);
L
Linus Torvalds 已提交
97 98 99 100

	/*
	 * Allocate a new parser op to be the root of the parsed tree
	 */
L
Len Brown 已提交
101
	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
L
Linus Torvalds 已提交
102
	if (!op) {
L
Len Brown 已提交
103
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
104 105 106 107 108 109 110 111
	}

	/* Save the Node for use in acpi_ps_parse_aml */

	op->common.node = scope_node;

	/* Create and initialize a new parser state */

L
Len Brown 已提交
112
	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
L
Linus Torvalds 已提交
113
	if (!walk_state) {
114 115
		status = AE_NO_MEMORY;
		goto cleanup;
L
Linus Torvalds 已提交
116 117
	}

L
Len Brown 已提交
118
	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
119
				       aml_length, NULL, ACPI_IMODE_LOAD_PASS1);
L
Len Brown 已提交
120 121
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
122
		goto cleanup;
L
Linus Torvalds 已提交
123 124 125 126 127 128 129 130 131
	}

	/* Mark this parse as a deferred opcode */

	walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
	walk_state->deferred_node = node;

	/* Pass1: Parse the entire declaration */

L
Len Brown 已提交
132 133
	status = acpi_ps_parse_aml(walk_state);
	if (ACPI_FAILURE(status)) {
134
		goto cleanup;
L
Linus Torvalds 已提交
135 136 137 138 139
	}

	/* Get and init the Op created above */

	op->common.node = node;
L
Len Brown 已提交
140
	acpi_ps_delete_parse_tree(op);
L
Linus Torvalds 已提交
141 142 143

	/* Evaluate the deferred arguments */

L
Len Brown 已提交
144
	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
L
Linus Torvalds 已提交
145
	if (!op) {
L
Len Brown 已提交
146
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
147 148 149 150 151 152
	}

	op->common.node = scope_node;

	/* Create and initialize a new parser state */

L
Len Brown 已提交
153
	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
L
Linus Torvalds 已提交
154
	if (!walk_state) {
155 156
		status = AE_NO_MEMORY;
		goto cleanup;
L
Linus Torvalds 已提交
157 158 159 160
	}

	/* Execute the opcode and arguments */

L
Len Brown 已提交
161
	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
162
				       aml_length, NULL, ACPI_IMODE_EXECUTE);
L
Len Brown 已提交
163 164
	if (ACPI_FAILURE(status)) {
		acpi_ds_delete_walk_state(walk_state);
165
		goto cleanup;
L
Linus Torvalds 已提交
166 167 168 169 170
	}

	/* Mark this execution as a deferred opcode */

	walk_state->deferred_node = node;
L
Len Brown 已提交
171
	status = acpi_ps_parse_aml(walk_state);
172

L
Len Brown 已提交
173 174 175
      cleanup:
	acpi_ps_delete_parse_tree(op);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
176 177
}

R
Robert Moore 已提交
178
/*******************************************************************************
L
Linus Torvalds 已提交
179 180 181 182 183 184 185 186 187 188
 *
 * FUNCTION:    acpi_ds_get_buffer_field_arguments
 *
 * PARAMETERS:  obj_desc        - A valid buffer_field object
 *
 * RETURN:      Status.
 *
 * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
 *              evaluation of these field attributes.
 *
R
Robert Moore 已提交
189
 ******************************************************************************/
L
Linus Torvalds 已提交
190 191

acpi_status
L
Len Brown 已提交
192
acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
L
Linus Torvalds 已提交
193
{
L
Len Brown 已提交
194 195 196
	union acpi_operand_object *extra_desc;
	struct acpi_namespace_node *node;
	acpi_status status;
L
Linus Torvalds 已提交
197

B
Bob Moore 已提交
198
	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
L
Linus Torvalds 已提交
199 200

	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
L
Len Brown 已提交
201
		return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
202 203 204 205
	}

	/* Get the AML pointer (method object) and buffer_field node */

L
Len Brown 已提交
206
	extra_desc = acpi_ns_get_secondary_object(obj_desc);
L
Linus Torvalds 已提交
207 208
	node = obj_desc->buffer_field.node;

L
Len Brown 已提交
209 210
	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_BUFFER_FIELD, node, NULL));
B
Bob Moore 已提交
211
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
L
Len Brown 已提交
212
			  acpi_ut_get_node_name(node)));
L
Linus Torvalds 已提交
213 214 215

	/* Execute the AML code for the term_arg arguments */

216
	status = acpi_ds_execute_arguments(node, node->parent,
L
Len Brown 已提交
217 218 219
					   extra_desc->extra.aml_length,
					   extra_desc->extra.aml_start);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
220 221
}

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_get_bank_field_arguments
 *
 * PARAMETERS:  obj_desc        - A valid bank_field object
 *
 * RETURN:      Status.
 *
 * DESCRIPTION: Get bank_field bank_value. This implements the late
 *              evaluation of these field attributes.
 *
 ******************************************************************************/

acpi_status
acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
{
	union acpi_operand_object *extra_desc;
	struct acpi_namespace_node *node;
	acpi_status status;

	ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);

	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
		return_ACPI_STATUS(AE_OK);
	}

	/* Get the AML pointer (method object) and bank_field node */

	extra_desc = acpi_ns_get_secondary_object(obj_desc);
	node = obj_desc->bank_field.node;

	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
			  acpi_ut_get_node_name(node)));

	/* Execute the AML code for the term_arg arguments */

260
	status = acpi_ds_execute_arguments(node, node->parent,
261 262 263 264 265
					   extra_desc->extra.aml_length,
					   extra_desc->extra.aml_start);
	return_ACPI_STATUS(status);
}

R
Robert Moore 已提交
266
/*******************************************************************************
L
Linus Torvalds 已提交
267 268 269 270 271 272 273 274 275 276
 *
 * FUNCTION:    acpi_ds_get_buffer_arguments
 *
 * PARAMETERS:  obj_desc        - A valid Buffer object
 *
 * RETURN:      Status.
 *
 * DESCRIPTION: Get Buffer length and initializer byte list.  This implements
 *              the late evaluation of these attributes.
 *
R
Robert Moore 已提交
277
 ******************************************************************************/
L
Linus Torvalds 已提交
278

L
Len Brown 已提交
279
acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
L
Linus Torvalds 已提交
280
{
L
Len Brown 已提交
281 282
	struct acpi_namespace_node *node;
	acpi_status status;
L
Linus Torvalds 已提交
283

B
Bob Moore 已提交
284
	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
L
Linus Torvalds 已提交
285 286

	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
L
Len Brown 已提交
287
		return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
288 289 290 291 292 293
	}

	/* Get the Buffer node */

	node = obj_desc->buffer.node;
	if (!node) {
B
Bob Moore 已提交
294
		ACPI_ERROR((AE_INFO,
295
			    "No pointer back to namespace node in buffer object %p",
B
Bob Moore 已提交
296
			    obj_desc));
L
Len Brown 已提交
297
		return_ACPI_STATUS(AE_AML_INTERNAL);
L
Linus Torvalds 已提交
298 299
	}

L
Len Brown 已提交
300
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
L
Linus Torvalds 已提交
301 302 303

	/* Execute the AML code for the term_arg arguments */

L
Len Brown 已提交
304 305 306 307
	status = acpi_ds_execute_arguments(node, node,
					   obj_desc->buffer.aml_length,
					   obj_desc->buffer.aml_start);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
308 309
}

R
Robert Moore 已提交
310
/*******************************************************************************
L
Linus Torvalds 已提交
311 312 313 314 315 316 317 318 319 320
 *
 * FUNCTION:    acpi_ds_get_package_arguments
 *
 * PARAMETERS:  obj_desc        - A valid Package object
 *
 * RETURN:      Status.
 *
 * DESCRIPTION: Get Package length and initializer byte list.  This implements
 *              the late evaluation of these attributes.
 *
R
Robert Moore 已提交
321
 ******************************************************************************/
L
Linus Torvalds 已提交
322

L
Len Brown 已提交
323
acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
L
Linus Torvalds 已提交
324
{
L
Len Brown 已提交
325 326
	struct acpi_namespace_node *node;
	acpi_status status;
L
Linus Torvalds 已提交
327

B
Bob Moore 已提交
328
	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
L
Linus Torvalds 已提交
329 330

	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
L
Len Brown 已提交
331
		return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
332 333 334 335 336 337
	}

	/* Get the Package node */

	node = obj_desc->package.node;
	if (!node) {
B
Bob Moore 已提交
338
		ACPI_ERROR((AE_INFO,
339
			    "No pointer back to namespace node in package %p",
B
Bob Moore 已提交
340
			    obj_desc));
L
Len Brown 已提交
341
		return_ACPI_STATUS(AE_AML_INTERNAL);
L
Linus Torvalds 已提交
342 343
	}

L
Len Brown 已提交
344
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
L
Linus Torvalds 已提交
345 346 347

	/* Execute the AML code for the term_arg arguments */

L
Len Brown 已提交
348 349 350 351
	status = acpi_ds_execute_arguments(node, node,
					   obj_desc->package.aml_length,
					   obj_desc->package.aml_start);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
}

/*****************************************************************************
 *
 * FUNCTION:    acpi_ds_get_region_arguments
 *
 * PARAMETERS:  obj_desc        - A valid region object
 *
 * RETURN:      Status.
 *
 * DESCRIPTION: Get region address and length.  This implements the late
 *              evaluation of these region attributes.
 *
 ****************************************************************************/

L
Len Brown 已提交
367
acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
L
Linus Torvalds 已提交
368
{
L
Len Brown 已提交
369 370 371
	struct acpi_namespace_node *node;
	acpi_status status;
	union acpi_operand_object *extra_desc;
L
Linus Torvalds 已提交
372

B
Bob Moore 已提交
373
	ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
L
Linus Torvalds 已提交
374 375

	if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
L
Len Brown 已提交
376
		return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
377 378
	}

L
Len Brown 已提交
379
	extra_desc = acpi_ns_get_secondary_object(obj_desc);
L
Linus Torvalds 已提交
380
	if (!extra_desc) {
L
Len Brown 已提交
381
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
382 383 384 385 386 387
	}

	/* Get the Region node */

	node = obj_desc->region.node;

L
Len Brown 已提交
388 389
	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_REGION, node, NULL));
L
Linus Torvalds 已提交
390

B
Bob Moore 已提交
391
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
L
Len Brown 已提交
392 393
			  acpi_ut_get_node_name(node),
			  extra_desc->extra.aml_start));
L
Linus Torvalds 已提交
394 395 396

	/* Execute the argument AML */

397
	status = acpi_ds_execute_arguments(node, node->parent,
L
Len Brown 已提交
398 399
					   extra_desc->extra.aml_length,
					   extra_desc->extra.aml_start);
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Validate the region address/length via the host OS */

	status = acpi_os_validate_address(obj_desc->region.space_id,
					  obj_desc->region.address,
					  (acpi_size) obj_desc->region.length,
					  acpi_ut_get_node_name(node));

	if (ACPI_FAILURE(status)) {
		/*
		 * Invalid address/length. We will emit an error message and mark
		 * the region as invalid, so that it will cause an additional error if
		 * it is ever used. Then return AE_OK.
		 */
		ACPI_EXCEPTION((AE_INFO, status,
				"During address validation of OpRegion [%4.4s]",
				node->name.ascii));
		obj_desc->common.flags |= AOPOBJ_INVALID;
		status = AE_OK;
	}

L
Len Brown 已提交
424
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
425 426
}

R
Robert Moore 已提交
427
/*******************************************************************************
L
Linus Torvalds 已提交
428 429 430
 *
 * FUNCTION:    acpi_ds_initialize_region
 *
R
Robert Moore 已提交
431
 * PARAMETERS:  obj_handle      - Region namespace node
L
Linus Torvalds 已提交
432 433 434 435 436
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Front end to ev_initialize_region
 *
R
Robert Moore 已提交
437
 ******************************************************************************/
L
Linus Torvalds 已提交
438

L
Len Brown 已提交
439
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
L
Linus Torvalds 已提交
440
{
L
Len Brown 已提交
441 442
	union acpi_operand_object *obj_desc;
	acpi_status status;
L
Linus Torvalds 已提交
443

L
Len Brown 已提交
444
	obj_desc = acpi_ns_get_attached_object(obj_handle);
L
Linus Torvalds 已提交
445 446 447

	/* Namespace is NOT locked */

L
Len Brown 已提交
448
	status = acpi_ev_initialize_region(obj_desc, FALSE);
L
Linus Torvalds 已提交
449 450 451
	return (status);
}

R
Robert Moore 已提交
452
/*******************************************************************************
L
Linus Torvalds 已提交
453 454 455 456 457 458 459
 *
 * FUNCTION:    acpi_ds_init_buffer_field
 *
 * PARAMETERS:  aml_opcode      - create_xxx_field
 *              obj_desc        - buffer_field object
 *              buffer_desc     - Host Buffer
 *              offset_desc     - Offset into buffer
R
Robert Moore 已提交
460 461
 *              length_desc     - Length of field (CREATE_FIELD_OP only)
 *              result_desc     - Where to store the result
L
Linus Torvalds 已提交
462 463 464 465 466
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform actual initialization of a buffer field
 *
R
Robert Moore 已提交
467
 ******************************************************************************/
L
Linus Torvalds 已提交
468

R
Robert Moore 已提交
469
static acpi_status
L
Len Brown 已提交
470 471 472 473 474 475
acpi_ds_init_buffer_field(u16 aml_opcode,
			  union acpi_operand_object *obj_desc,
			  union acpi_operand_object *buffer_desc,
			  union acpi_operand_object *offset_desc,
			  union acpi_operand_object *length_desc,
			  union acpi_operand_object *result_desc)
L
Linus Torvalds 已提交
476
{
L
Len Brown 已提交
477 478 479 480 481
	u32 offset;
	u32 bit_offset;
	u32 bit_count;
	u8 field_flags;
	acpi_status status;
L
Linus Torvalds 已提交
482

B
Bob Moore 已提交
483
	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
L
Linus Torvalds 已提交
484 485 486

	/* Host object must be a Buffer */

487
	if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
B
Bob Moore 已提交
488 489 490
		ACPI_ERROR((AE_INFO,
			    "Target of Create Field is not a Buffer object - %s",
			    acpi_ut_get_object_type_name(buffer_desc)));
L
Linus Torvalds 已提交
491 492 493 494 495 496 497 498 499 500

		status = AE_AML_OPERAND_TYPE;
		goto cleanup;
	}

	/*
	 * The last parameter to all of these opcodes (result_desc) started
	 * out as a name_string, and should therefore now be a NS node
	 * after resolution in acpi_ex_resolve_operands().
	 */
L
Len Brown 已提交
501
	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
B
Bob Moore 已提交
502 503 504 505
		ACPI_ERROR((AE_INFO,
			    "(%s) destination not a NS Node [%s]",
			    acpi_ps_get_opcode_name(aml_opcode),
			    acpi_ut_get_descriptor_name(result_desc)));
L
Linus Torvalds 已提交
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520

		status = AE_AML_OPERAND_TYPE;
		goto cleanup;
	}

	offset = (u32) offset_desc->integer.value;

	/*
	 * Setup the Bit offsets and counts, according to the opcode
	 */
	switch (aml_opcode) {
	case AML_CREATE_FIELD_OP:

		/* Offset is in bits, count is in bits */

R
Robert Moore 已提交
521
		field_flags = AML_FIELD_ACCESS_BYTE;
L
Linus Torvalds 已提交
522
		bit_offset = offset;
L
Len Brown 已提交
523
		bit_count = (u32) length_desc->integer.value;
R
Robert Moore 已提交
524 525 526 527

		/* Must have a valid (>0) bit count */

		if (bit_count == 0) {
B
Bob Moore 已提交
528
			ACPI_ERROR((AE_INFO,
B
Bob Moore 已提交
529
				    "Attempt to CreateField of length zero"));
R
Robert Moore 已提交
530 531 532
			status = AE_AML_OPERAND_VALUE;
			goto cleanup;
		}
L
Linus Torvalds 已提交
533 534 535 536 537 538 539
		break;

	case AML_CREATE_BIT_FIELD_OP:

		/* Offset is in bits, Field is one bit */

		bit_offset = offset;
L
Len Brown 已提交
540
		bit_count = 1;
L
Linus Torvalds 已提交
541 542 543 544 545 546 547 548
		field_flags = AML_FIELD_ACCESS_BYTE;
		break;

	case AML_CREATE_BYTE_FIELD_OP:

		/* Offset is in bytes, field is one byte */

		bit_offset = 8 * offset;
L
Len Brown 已提交
549
		bit_count = 8;
L
Linus Torvalds 已提交
550 551 552 553 554 555 556 557
		field_flags = AML_FIELD_ACCESS_BYTE;
		break;

	case AML_CREATE_WORD_FIELD_OP:

		/* Offset is in bytes, field is one word */

		bit_offset = 8 * offset;
L
Len Brown 已提交
558
		bit_count = 16;
L
Linus Torvalds 已提交
559 560 561 562 563 564 565 566
		field_flags = AML_FIELD_ACCESS_WORD;
		break;

	case AML_CREATE_DWORD_FIELD_OP:

		/* Offset is in bytes, field is one dword */

		bit_offset = 8 * offset;
L
Len Brown 已提交
567
		bit_count = 32;
L
Linus Torvalds 已提交
568 569 570 571 572 573 574 575
		field_flags = AML_FIELD_ACCESS_DWORD;
		break;

	case AML_CREATE_QWORD_FIELD_OP:

		/* Offset is in bytes, field is one qword */

		bit_offset = 8 * offset;
L
Len Brown 已提交
576
		bit_count = 64;
L
Linus Torvalds 已提交
577 578 579 580 581
		field_flags = AML_FIELD_ACCESS_QWORD;
		break;

	default:

B
Bob Moore 已提交
582
		ACPI_ERROR((AE_INFO,
583 584
			    "Unknown field creation opcode 0x%02X",
			    aml_opcode));
L
Linus Torvalds 已提交
585 586 587 588 589 590
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

	/* Entire field must fit within the current length of the buffer */

L
Len Brown 已提交
591
	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
B
Bob Moore 已提交
592
		ACPI_ERROR((AE_INFO,
593
			    "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)",
B
Bob Moore 已提交
594 595 596 597
			    acpi_ut_get_node_name(result_desc),
			    bit_offset + bit_count,
			    acpi_ut_get_node_name(buffer_desc->buffer.node),
			    8 * (u32) buffer_desc->buffer.length));
L
Linus Torvalds 已提交
598 599 600 601 602 603
		status = AE_AML_BUFFER_LIMIT;
		goto cleanup;
	}

	/*
	 * Initialize areas of the field object that are common to all fields
R
Robert Moore 已提交
604 605
	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
L
Linus Torvalds 已提交
606
	 */
L
Len Brown 已提交
607 608 609
	status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
						  bit_offset, bit_count);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
610 611 612 613 614 615 616
		goto cleanup;
	}

	obj_desc->buffer_field.buffer_obj = buffer_desc;

	/* Reference count for buffer_desc inherits obj_desc count */

R
Robert Moore 已提交
617
	buffer_desc->common.reference_count = (u16)
L
Len Brown 已提交
618 619
	    (buffer_desc->common.reference_count +
	     obj_desc->common.reference_count);
L
Linus Torvalds 已提交
620

L
Len Brown 已提交
621
      cleanup:
L
Linus Torvalds 已提交
622 623 624

	/* Always delete the operands */

L
Len Brown 已提交
625 626
	acpi_ut_remove_reference(offset_desc);
	acpi_ut_remove_reference(buffer_desc);
L
Linus Torvalds 已提交
627 628

	if (aml_opcode == AML_CREATE_FIELD_OP) {
L
Len Brown 已提交
629
		acpi_ut_remove_reference(length_desc);
L
Linus Torvalds 已提交
630 631 632 633
	}

	/* On failure, delete the result descriptor */

L
Len Brown 已提交
634 635 636
	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
	} else {
L
Linus Torvalds 已提交
637 638 639 640 641
		/* Now the address and length are valid for this buffer_field */

		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
	}

L
Len Brown 已提交
642
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
643 644
}

R
Robert Moore 已提交
645
/*******************************************************************************
L
Linus Torvalds 已提交
646 647 648 649 650 651 652 653 654 655 656
 *
 * FUNCTION:    acpi_ds_eval_buffer_field_operands
 *
 * PARAMETERS:  walk_state      - Current walk
 *              Op              - A valid buffer_field Op object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get buffer_field Buffer and Index
 *              Called from acpi_ds_exec_end_op during buffer_field parse tree walk
 *
R
Robert Moore 已提交
657
 ******************************************************************************/
L
Linus Torvalds 已提交
658 659

acpi_status
L
Len Brown 已提交
660 661
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
L
Linus Torvalds 已提交
662
{
L
Len Brown 已提交
663 664 665 666
	acpi_status status;
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
L
Linus Torvalds 已提交
667

B
Bob Moore 已提交
668
	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
L
Linus Torvalds 已提交
669 670 671 672 673

	/*
	 * This is where we evaluate the address and length fields of the
	 * create_xxx_field declaration
	 */
L
Len Brown 已提交
674
	node = op->common.node;
L
Linus Torvalds 已提交
675 676 677 678 679 680 681

	/* next_op points to the op that holds the Buffer */

	next_op = op->common.value.arg;

	/* Evaluate/create the address and length operands */

L
Len Brown 已提交
682 683 684
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
685 686
	}

L
Len Brown 已提交
687
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
688
	if (!obj_desc) {
L
Len Brown 已提交
689
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
690 691 692 693
	}

	/* Resolve the operands */

L
Len Brown 已提交
694 695 696
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
697
		ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
B
Bob Moore 已提交
698 699
			    acpi_ps_get_opcode_name(op->common.aml_opcode),
			    status));
L
Linus Torvalds 已提交
700

L
Len Brown 已提交
701
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
702 703 704 705 706
	}

	/* Initialize the Buffer Field */

	if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
B
Bob Moore 已提交
707

L
Linus Torvalds 已提交
708 709
		/* NOTE: Slightly different operands for this opcode */

L
Len Brown 已提交
710 711 712 713 714 715 716
		status =
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
					      walk_state->operands[0],
					      walk_state->operands[1],
					      walk_state->operands[2],
					      walk_state->operands[3]);
	} else {
L
Linus Torvalds 已提交
717 718
		/* All other, create_xxx_field opcodes */

L
Len Brown 已提交
719 720 721 722 723
		status =
		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
					      walk_state->operands[0],
					      walk_state->operands[1], NULL,
					      walk_state->operands[2]);
L
Linus Torvalds 已提交
724 725
	}

L
Len Brown 已提交
726
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
727 728
}

R
Robert Moore 已提交
729
/*******************************************************************************
L
Linus Torvalds 已提交
730 731 732 733 734 735 736 737 738 739 740
 *
 * FUNCTION:    acpi_ds_eval_region_operands
 *
 * PARAMETERS:  walk_state      - Current walk
 *              Op              - A valid region Op object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get region address and length
 *              Called from acpi_ds_exec_end_op during op_region parse tree walk
 *
R
Robert Moore 已提交
741
 ******************************************************************************/
L
Linus Torvalds 已提交
742 743

acpi_status
L
Len Brown 已提交
744 745
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
L
Linus Torvalds 已提交
746
{
L
Len Brown 已提交
747 748 749 750 751
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *operand_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
L
Linus Torvalds 已提交
752

B
Bob Moore 已提交
753
	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
L
Linus Torvalds 已提交
754 755

	/*
R
Robert Moore 已提交
756 757
	 * This is where we evaluate the address and length fields of the
	 * op_region declaration
L
Linus Torvalds 已提交
758
	 */
L
Len Brown 已提交
759
	node = op->common.node;
L
Linus Torvalds 已提交
760 761 762 763 764 765 766 767 768 769 770

	/* next_op points to the op that holds the space_iD */

	next_op = op->common.value.arg;

	/* next_op points to address op */

	next_op = next_op->common.next;

	/* Evaluate/create the address and length operands */

L
Len Brown 已提交
771 772 773
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
774 775 776 777
	}

	/* Resolve the length and address operands to numbers */

L
Len Brown 已提交
778 779 780 781
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
782 783
	}

L
Len Brown 已提交
784
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
785
	if (!obj_desc) {
L
Len Brown 已提交
786
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
787 788 789 790 791 792 793 794 795
	}

	/*
	 * Get the length operand and save it
	 * (at Top of stack)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 1];

	obj_desc->region.length = (u32) operand_desc->integer.value;
L
Len Brown 已提交
796
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
797 798 799 800 801 802 803

	/*
	 * Get the address and save it
	 * (at top of stack - 1)
	 */
	operand_desc = walk_state->operands[walk_state->num_operands - 2];

R
Robert Moore 已提交
804
	obj_desc->region.address = (acpi_physical_address)
L
Len Brown 已提交
805 806
	    operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
807

B
Bob Moore 已提交
808
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
L
Len Brown 已提交
809
			  obj_desc,
810
			  ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
L
Len Brown 已提交
811
			  obj_desc->region.length));
L
Linus Torvalds 已提交
812 813 814 815 816

	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

L
Len Brown 已提交
817
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
818 819
}

820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842
/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_eval_table_region_operands
 *
 * PARAMETERS:  walk_state      - Current walk
 *              Op              - A valid region Op object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get region address and length
 *              Called from acpi_ds_exec_end_op during data_table_region parse tree walk
 *
 ******************************************************************************/

acpi_status
acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object **operand;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
843
	u32 table_index;
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917
	struct acpi_table_header *table;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);

	/*
	 * This is where we evaluate the signature_string and oem_iDString
	 * and oem_table_iDString of the data_table_region declaration
	 */
	node = op->common.node;

	/* next_op points to signature_string op */

	next_op = op->common.value.arg;

	/*
	 * Evaluate/create the signature_string and oem_iDString
	 * and oem_table_iDString operands
	 */
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/*
	 * Resolve the signature_string and oem_iDString
	 * and oem_table_iDString operands
	 */
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	operand = &walk_state->operands[0];

	/* Find the ACPI table */

	status = acpi_tb_find_table(operand[0]->string.pointer,
				    operand[1]->string.pointer,
				    operand[2]->string.pointer, &table_index);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	acpi_ut_remove_reference(operand[0]);
	acpi_ut_remove_reference(operand[1]);
	acpi_ut_remove_reference(operand[2]);

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NOT_EXIST);
	}

	obj_desc->region.address =
	    (acpi_physical_address) ACPI_TO_INTEGER(table);
	obj_desc->region.length = table->length;

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
			  ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
			  obj_desc->region.length));

	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

	return_ACPI_STATUS(status);
}

R
Robert Moore 已提交
918
/*******************************************************************************
L
Linus Torvalds 已提交
919 920 921 922 923 924 925 926 927 928 929 930
 *
 * FUNCTION:    acpi_ds_eval_data_object_operands
 *
 * PARAMETERS:  walk_state      - Current walk
 *              Op              - A valid data_object Op object
 *              obj_desc        - data_object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get the operands and complete the following data object types:
 *              Buffer, Package.
 *
R
Robert Moore 已提交
931
 ******************************************************************************/
L
Linus Torvalds 已提交
932 933

acpi_status
L
Len Brown 已提交
934 935 936
acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
				  union acpi_parse_object *op,
				  union acpi_operand_object *obj_desc)
L
Linus Torvalds 已提交
937
{
L
Len Brown 已提交
938 939 940
	acpi_status status;
	union acpi_operand_object *arg_desc;
	u32 length;
L
Linus Torvalds 已提交
941

B
Bob Moore 已提交
942
	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
L
Linus Torvalds 已提交
943 944 945

	/* The first operand (for all of these data objects) is the length */

946 947 948 949 950 951
	/*
	 * Set proper index into operand stack for acpi_ds_obj_stack_push
	 * invoked inside acpi_ds_create_operand.
	 */
	walk_state->operand_index = walk_state->num_operands;

L
Len Brown 已提交
952 953 954
	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
955 956
	}

L
Len Brown 已提交
957 958 959 960 961 962
	status = acpi_ex_resolve_operands(walk_state->opcode,
					  &(walk_state->
					    operands[walk_state->num_operands -
						     1]), walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
963 964 965 966
	}

	/* Extract length operand */

L
Len Brown 已提交
967
	arg_desc = walk_state->operands[walk_state->num_operands - 1];
L
Linus Torvalds 已提交
968 969 970 971
	length = (u32) arg_desc->integer.value;

	/* Cleanup for length operand */

L
Len Brown 已提交
972 973 974
	status = acpi_ds_obj_stack_pop(1, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
975 976
	}

L
Len Brown 已提交
977
	acpi_ut_remove_reference(arg_desc);
L
Linus Torvalds 已提交
978 979 980 981 982 983 984

	/*
	 * Create the actual data object
	 */
	switch (op->common.aml_opcode) {
	case AML_BUFFER_OP:

L
Len Brown 已提交
985 986 987
		status =
		    acpi_ds_build_internal_buffer_obj(walk_state, op, length,
						      &obj_desc);
L
Linus Torvalds 已提交
988 989 990 991 992
		break;

	case AML_PACKAGE_OP:
	case AML_VAR_PACKAGE_OP:

L
Len Brown 已提交
993 994 995
		status =
		    acpi_ds_build_internal_package_obj(walk_state, op, length,
						       &obj_desc);
L
Linus Torvalds 已提交
996 997 998
		break;

	default:
L
Len Brown 已提交
999
		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
L
Linus Torvalds 已提交
1000 1001
	}

L
Len Brown 已提交
1002
	if (ACPI_SUCCESS(status)) {
L
Linus Torvalds 已提交
1003
		/*
R
Robert Moore 已提交
1004
		 * Return the object in the walk_state, unless the parent is a package -
L
Linus Torvalds 已提交
1005 1006 1007 1008
		 * in this case, the return object will be stored in the parse tree
		 * for the package.
		 */
		if ((!op->common.parent) ||
L
Len Brown 已提交
1009 1010 1011
		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
		     (op->common.parent->common.aml_opcode !=
		      AML_VAR_PACKAGE_OP)
L
Len Brown 已提交
1012
		     && (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
L
Linus Torvalds 已提交
1013 1014 1015 1016
			walk_state->result_obj = obj_desc;
		}
	}

L
Len Brown 已提交
1017
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
1018 1019
}

1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_eval_bank_field_operands
 *
 * PARAMETERS:  walk_state      - Current walk
 *              Op              - A valid bank_field Op object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get bank_field bank_value
 *              Called from acpi_ds_exec_end_op during bank_field parse tree walk
 *
 ******************************************************************************/

acpi_status
acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
				 union acpi_parse_object *op)
{
	acpi_status status;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *operand_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
	union acpi_parse_object *arg;

	ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);

	/*
	 * This is where we evaluate the bank_value field of the
	 * bank_field declaration
	 */

	/* next_op points to the op that holds the Region */

	next_op = op->common.value.arg;

	/* next_op points to the op that holds the Bank Register */

	next_op = next_op->common.next;

	/* next_op points to the op that holds the Bank Value */

	next_op = next_op->common.next;

	/*
	 * Set proper index into operand stack for acpi_ds_obj_stack_push
	 * invoked inside acpi_ds_create_operand.
	 *
	 * We use walk_state->Operands[0] to store the evaluated bank_value
	 */
	walk_state->operand_index = 0;

	status = acpi_ds_create_operand(walk_state, next_op, 0);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

1082 1083
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
	/*
	 * Get the bank_value operand and save it
	 * (at Top of stack)
	 */
	operand_desc = walk_state->operands[0];

	/* Arg points to the start Bank Field */

	arg = acpi_ps_get_arg(op, 4);
	while (arg) {

		/* Ignore OFFSET and ACCESSAS terms here */

		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
			node = arg->common.node;

			obj_desc = acpi_ns_get_attached_object(node);
			if (!obj_desc) {
				return_ACPI_STATUS(AE_NOT_EXIST);
			}

			obj_desc->bank_field.value =
			    (u32) operand_desc->integer.value;
		}

		/* Move to next field in the list */

		arg = arg->common.next;
	}

	acpi_ut_remove_reference(operand_desc);
	return_ACPI_STATUS(status);
}

L
Linus Torvalds 已提交
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_exec_begin_control_op
 *
 * PARAMETERS:  walk_list       - The list that owns the walk stack
 *              Op              - The control Op
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handles all control ops encountered during control method
 *              execution.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
1133 1134
acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
			      union acpi_parse_object *op)
L
Linus Torvalds 已提交
1135
{
L
Len Brown 已提交
1136 1137
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
1138

B
Bob Moore 已提交
1139
	ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
L
Linus Torvalds 已提交
1140

L
Len Brown 已提交
1141 1142
	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
			  op->common.aml_opcode, walk_state));
L
Linus Torvalds 已提交
1143 1144 1145 1146

	switch (op->common.aml_opcode) {
	case AML_WHILE_OP:

1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
		/*
		 * If this is an additional iteration of a while loop, continue.
		 * There is no need to allocate a new control state.
		 */
		if (walk_state->control_state) {
			if (walk_state->control_state->control.aml_predicate_start
				== (walk_state->parser_state.aml - 1)) {

				/* Reset the state to start-of-loop */

				walk_state->control_state->common.state =
				    ACPI_CONTROL_CONDITIONAL_EXECUTING;
				break;
			}
		}

		/*lint -fallthrough */

	case AML_IF_OP:

L
Linus Torvalds 已提交
1167 1168 1169 1170 1171
		/*
		 * IF/WHILE: Create a new control state to manage these
		 * constructs. We need to manage these as a stack, in order
		 * to handle nesting.
		 */
L
Len Brown 已提交
1172
		control_state = acpi_ut_create_control_state();
L
Linus Torvalds 已提交
1173 1174 1175 1176 1177 1178 1179 1180
		if (!control_state) {
			status = AE_NO_MEMORY;
			break;
		}
		/*
		 * Save a pointer to the predicate for multiple executions
		 * of a loop
		 */
L
Len Brown 已提交
1181 1182 1183 1184
		control_state->control.aml_predicate_start =
		    walk_state->parser_state.aml - 1;
		control_state->control.package_end =
		    walk_state->parser_state.pkg_end;
L
Linus Torvalds 已提交
1185 1186 1187 1188
		control_state->control.opcode = op->common.aml_opcode;

		/* Push the control state on this walk's control stack */

L
Len Brown 已提交
1189 1190
		acpi_ut_push_generic_state(&walk_state->control_state,
					   control_state);
L
Linus Torvalds 已提交
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
		break;

	case AML_ELSE_OP:

		/* Predicate is in the state object */
		/* If predicate is true, the IF was executed, ignore ELSE part */

		if (walk_state->last_predicate) {
			status = AE_CTRL_TRUE;
		}

		break;

	case AML_RETURN_OP:

		break;

	default:
		break;
	}

	return (status);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_exec_end_control_op
 *
 * PARAMETERS:  walk_list       - The list that owns the walk stack
 *              Op              - The control Op
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Handles all control ops encountered during control method
 *              execution.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
1230 1231
acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
			    union acpi_parse_object * op)
L
Linus Torvalds 已提交
1232
{
L
Len Brown 已提交
1233 1234
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
1235

B
Bob Moore 已提交
1236
	ACPI_FUNCTION_NAME(ds_exec_end_control_op);
L
Linus Torvalds 已提交
1237 1238 1239 1240

	switch (op->common.aml_opcode) {
	case AML_IF_OP:

L
Len Brown 已提交
1241
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
L
Linus Torvalds 已提交
1242 1243 1244 1245 1246 1247

		/*
		 * Save the result of the predicate in case there is an
		 * ELSE to come
		 */
		walk_state->last_predicate =
L
Len Brown 已提交
1248
		    (u8) walk_state->control_state->common.value;
L
Linus Torvalds 已提交
1249 1250 1251 1252 1253

		/*
		 * Pop the control state that was created at the start
		 * of the IF and free it
		 */
L
Len Brown 已提交
1254 1255 1256
		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);
		acpi_ut_delete_generic_state(control_state);
L
Linus Torvalds 已提交
1257 1258 1259 1260 1261 1262 1263 1264
		break;

	case AML_ELSE_OP:

		break;

	case AML_WHILE_OP:

L
Len Brown 已提交
1265
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
L
Linus Torvalds 已提交
1266

1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283
		control_state = walk_state->control_state;
		if (control_state->common.value) {

			/* Predicate was true, the body of the loop was just executed */

			/*
			 * This loop counter mechanism allows the interpreter to escape
			 * possibly infinite loops. This can occur in poorly written AML
			 * when the hardware does not respond within a while loop and the
			 * loop does not implement a timeout.
			 */
			control_state->control.loop_count++;
			if (control_state->control.loop_count >
				ACPI_MAX_LOOP_ITERATIONS) {
				status = AE_AML_INFINITE_LOOP;
				break;
			}
L
Linus Torvalds 已提交
1284

1285 1286 1287 1288
			/*
			 * Go back and evaluate the predicate and maybe execute the loop
			 * another time
			 */
L
Linus Torvalds 已提交
1289
			status = AE_CTRL_PENDING;
1290
			walk_state->aml_last_while =
1291
			    control_state->control.aml_predicate_start;
1292
			break;
L
Linus Torvalds 已提交
1293 1294
		}

1295 1296
		/* Predicate was false, terminate this while loop */

L
Len Brown 已提交
1297 1298
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[WHILE_OP] termination! Op=%p\n", op));
L
Linus Torvalds 已提交
1299 1300 1301

		/* Pop this control state and free it */

L
Len Brown 已提交
1302 1303 1304
		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);
		acpi_ut_delete_generic_state(control_state);
L
Linus Torvalds 已提交
1305 1306 1307 1308
		break;

	case AML_RETURN_OP:

L
Len Brown 已提交
1309 1310 1311
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[RETURN_OP] Op=%p Arg=%p\n", op,
				  op->common.value.arg));
L
Linus Torvalds 已提交
1312 1313 1314 1315 1316 1317 1318

		/*
		 * One optional operand -- the return value
		 * It can be either an immediate operand or a result that
		 * has been bubbled up the tree
		 */
		if (op->common.value.arg) {
B
Bob Moore 已提交
1319

L
Linus Torvalds 已提交
1320 1321
			/* Since we have a real Return(), delete any implicit return */

L
Len Brown 已提交
1322
			acpi_ds_clear_implicit_return(walk_state);
L
Linus Torvalds 已提交
1323 1324 1325

			/* Return statement has an immediate operand */

L
Len Brown 已提交
1326 1327 1328 1329
			status =
			    acpi_ds_create_operands(walk_state,
						    op->common.value.arg);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1330 1331 1332 1333 1334 1335 1336 1337
				return (status);
			}

			/*
			 * If value being returned is a Reference (such as
			 * an arg or local), resolve it now because it may
			 * cease to exist at the end of the method.
			 */
L
Len Brown 已提交
1338 1339 1340 1341
			status =
			    acpi_ex_resolve_to_value(&walk_state->operands[0],
						     walk_state);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1342 1343 1344 1345 1346 1347 1348 1349 1350
				return (status);
			}

			/*
			 * Get the return value and save as the last result
			 * value.  This is the only place where walk_state->return_desc
			 * is set to anything other than zero!
			 */
			walk_state->return_desc = walk_state->operands[0];
1351
		} else if (walk_state->result_count) {
B
Bob Moore 已提交
1352

L
Linus Torvalds 已提交
1353 1354
			/* Since we have a real Return(), delete any implicit return */

L
Len Brown 已提交
1355
			acpi_ds_clear_implicit_return(walk_state);
L
Linus Torvalds 已提交
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365

			/*
			 * The return value has come from a previous calculation.
			 *
			 * If value being returned is a Reference (such as
			 * an arg or local), resolve it now because it may
			 * cease to exist at the end of the method.
			 *
			 * Allow references created by the Index operator to return unchanged.
			 */
L
Len Brown 已提交
1366 1367 1368
			if ((ACPI_GET_DESCRIPTOR_TYPE
			     (walk_state->results->results.obj_desc[0]) ==
			     ACPI_DESC_TYPE_OPERAND)
1369 1370
			    && ((walk_state->results->results.obj_desc[0])->
				common.type == ACPI_TYPE_LOCAL_REFERENCE)
L
Len Brown 已提交
1371
			    && ((walk_state->results->results.obj_desc[0])->
1372
				reference.class != ACPI_REFCLASS_INDEX)) {
L
Len Brown 已提交
1373 1374 1375 1376 1377 1378
				status =
				    acpi_ex_resolve_to_value(&walk_state->
							     results->results.
							     obj_desc[0],
							     walk_state);
				if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1379 1380 1381 1382
					return (status);
				}
			}

L
Len Brown 已提交
1383 1384 1385
			walk_state->return_desc =
			    walk_state->results->results.obj_desc[0];
		} else {
L
Linus Torvalds 已提交
1386 1387 1388
			/* No return operand */

			if (walk_state->num_operands) {
L
Len Brown 已提交
1389 1390
				acpi_ut_remove_reference(walk_state->
							 operands[0]);
L
Linus Torvalds 已提交
1391 1392
			}

L
Len Brown 已提交
1393 1394 1395
			walk_state->operands[0] = NULL;
			walk_state->num_operands = 0;
			walk_state->return_desc = NULL;
L
Linus Torvalds 已提交
1396 1397
		}

L
Len Brown 已提交
1398
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
B
Bob Moore 已提交
1399
				  "Completed RETURN_OP State=%p, RetVal=%p\n",
L
Len Brown 已提交
1400
				  walk_state, walk_state->return_desc));
L
Linus Torvalds 已提交
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413

		/* End the control method execution right now */

		status = AE_CTRL_TERMINATE;
		break;

	case AML_NOOP_OP:

		/* Just do nothing! */
		break;

	case AML_BREAK_POINT_OP:

1414 1415 1416 1417 1418 1419 1420 1421
		/*
		 * Set the single-step flag. This will cause the debugger (if present)
		 * to break to the console within the AML debugger at the start of the
		 * next AML instruction.
		 */
		ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE);
		ACPI_DEBUGGER_EXEC(acpi_os_printf
				   ("**break** Executed AML BreakPoint opcode\n"));
L
Linus Torvalds 已提交
1422

1423
		/* Call to the OSL in case OS wants a piece of the action */
L
Linus Torvalds 已提交
1424

1425 1426
		status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
					"Executed AML Breakpoint opcode");
L
Linus Torvalds 已提交
1427 1428 1429
		break;

	case AML_BREAK_OP:
L
Len Brown 已提交
1430
	case AML_CONTINUE_OP:	/* ACPI 2.0 */
L
Linus Torvalds 已提交
1431 1432 1433 1434

		/* Pop and delete control states until we find a while */

		while (walk_state->control_state &&
L
Len Brown 已提交
1435 1436 1437 1438 1439 1440
		       (walk_state->control_state->control.opcode !=
			AML_WHILE_OP)) {
			control_state =
			    acpi_ut_pop_generic_state(&walk_state->
						      control_state);
			acpi_ut_delete_generic_state(control_state);
L
Linus Torvalds 已提交
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450
		}

		/* No while found? */

		if (!walk_state->control_state) {
			return (AE_AML_NO_WHILE);
		}

		/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */

L
Len Brown 已提交
1451 1452
		walk_state->aml_last_while =
		    walk_state->control_state->control.package_end;
L
Linus Torvalds 已提交
1453 1454 1455 1456 1457

		/* Return status depending on opcode */

		if (op->common.aml_opcode == AML_BREAK_OP) {
			status = AE_CTRL_BREAK;
L
Len Brown 已提交
1458
		} else {
L
Linus Torvalds 已提交
1459 1460 1461 1462 1463 1464
			status = AE_CTRL_CONTINUE;
		}
		break;

	default:

1465
		ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p",
B
Bob Moore 已提交
1466
			    op->common.aml_opcode, op));
L
Linus Torvalds 已提交
1467 1468 1469 1470 1471 1472 1473

		status = AE_AML_BAD_OPCODE;
		break;
	}

	return (status);
}