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 - 2010, 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 */

L
Len Brown 已提交
216 217 218 219
	status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
					   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 260 261 262 263 264 265
/*******************************************************************************
 *
 * 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 */

	status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
					   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 295 296
		ACPI_ERROR((AE_INFO,
			    "No pointer back to NS node in buffer obj %p",
			    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 339 340
		ACPI_ERROR((AE_INFO,
			    "No pointer back to NS node in package %p",
			    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 */

L
Len Brown 已提交
397 398 399
	status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
					   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 583
		ACPI_ERROR((AE_INFO,
			    "Unknown field creation opcode %02x", aml_opcode));
L
Linus Torvalds 已提交
584 585 586 587 588 589
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

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

L
Len Brown 已提交
590
	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
B
Bob Moore 已提交
591 592 593 594 595 596
		ACPI_ERROR((AE_INFO,
			    "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)",
			    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 已提交
597 598 599 600 601 602
		status = AE_AML_BUFFER_LIMIT;
		goto cleanup;
	}

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

	obj_desc->buffer_field.buffer_obj = buffer_desc;

	/* Reference count for buffer_desc inherits obj_desc count */

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

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

	/* Always delete the operands */

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

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

	/* On failure, delete the result descriptor */

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

		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
	}

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

R
Robert Moore 已提交
644
/*******************************************************************************
L
Linus Torvalds 已提交
645 646 647 648 649 650 651 652 653 654 655
 *
 * 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 已提交
656
 ******************************************************************************/
L
Linus Torvalds 已提交
657 658

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

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

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

	/* 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 已提交
681 682 683
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
684 685
	}

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

	/* Resolve the operands */

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

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

	/* Initialize the Buffer Field */

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

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

L
Len Brown 已提交
709 710 711 712 713 714 715
		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 已提交
716 717
		/* All other, create_xxx_field opcodes */

L
Len Brown 已提交
718 719 720 721 722
		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 已提交
723 724
	}

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

R
Robert Moore 已提交
728
/*******************************************************************************
L
Linus Torvalds 已提交
729 730 731 732 733 734 735 736 737 738 739
 *
 * 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 已提交
740
 ******************************************************************************/
L
Linus Torvalds 已提交
741 742

acpi_status
L
Len Brown 已提交
743 744
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
L
Linus Torvalds 已提交
745
{
L
Len Brown 已提交
746 747 748 749 750
	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 已提交
751

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

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

	/* 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 已提交
770 771 772
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
773 774 775 776
	}

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

L
Len Brown 已提交
777 778 779 780
	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 已提交
781 782
	}

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

	/*
	 * 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 已提交
795
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
796 797 798 799 800 801 802

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

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

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

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

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

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

819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
/*******************************************************************************
 *
 * 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;
842
	u32 table_index;
843 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
	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 已提交
917
/*******************************************************************************
L
Linus Torvalds 已提交
918 919 920 921 922 923 924 925 926 927 928 929
 *
 * 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 已提交
930
 ******************************************************************************/
L
Linus Torvalds 已提交
931 932

acpi_status
L
Len Brown 已提交
933 934 935
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 已提交
936
{
L
Len Brown 已提交
937 938 939
	acpi_status status;
	union acpi_operand_object *arg_desc;
	u32 length;
L
Linus Torvalds 已提交
940

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

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

945 946 947 948 949 950
	/*
	 * 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 已提交
951 952 953
	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
954 955
	}

L
Len Brown 已提交
956 957 958 959 960 961
	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 已提交
962 963 964 965
	}

	/* Extract length operand */

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

	/* Cleanup for length operand */

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

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

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

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

	case AML_PACKAGE_OP:
	case AML_VAR_PACKAGE_OP:

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

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

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

L
Len Brown 已提交
1016
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
1017 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
/*******************************************************************************
 *
 * 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);
	}

1081 1082
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
1083 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
	/*
	 * 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 已提交
1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
/*******************************************************************************
 *
 * 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 已提交
1132 1133
acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
			      union acpi_parse_object *op)
L
Linus Torvalds 已提交
1134
{
L
Len Brown 已提交
1135 1136
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
1137

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

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

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

1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
		/*
		 * 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 已提交
1166 1167 1168 1169 1170
		/*
		 * 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 已提交
1171
		control_state = acpi_ut_create_control_state();
L
Linus Torvalds 已提交
1172 1173 1174 1175 1176 1177 1178 1179
		if (!control_state) {
			status = AE_NO_MEMORY;
			break;
		}
		/*
		 * Save a pointer to the predicate for multiple executions
		 * of a loop
		 */
L
Len Brown 已提交
1180 1181 1182 1183
		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 已提交
1184 1185 1186 1187
		control_state->control.opcode = op->common.aml_opcode;

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

L
Len Brown 已提交
1188 1189
		acpi_ut_push_generic_state(&walk_state->control_state,
					   control_state);
L
Linus Torvalds 已提交
1190 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
		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 已提交
1229 1230
acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
			    union acpi_parse_object * op)
L
Linus Torvalds 已提交
1231
{
L
Len Brown 已提交
1232 1233
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
1234

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

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

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

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

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

	case AML_ELSE_OP:

		break;

	case AML_WHILE_OP:

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

1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
		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 已提交
1283

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

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

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

		/* Pop this control state and free it */

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

	case AML_RETURN_OP:

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

		/*
		 * 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 已提交
1318

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

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

			/* Return statement has an immediate operand */

L
Len Brown 已提交
1325 1326 1327 1328
			status =
			    acpi_ds_create_operands(walk_state,
						    op->common.value.arg);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1329 1330 1331 1332 1333 1334 1335 1336
				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 已提交
1337 1338 1339 1340
			status =
			    acpi_ex_resolve_to_value(&walk_state->operands[0],
						     walk_state);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1341 1342 1343 1344 1345 1346 1347 1348 1349
				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];
1350
		} else if (walk_state->result_count) {
B
Bob Moore 已提交
1351

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

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

			/*
			 * 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 已提交
1365 1366 1367
			if ((ACPI_GET_DESCRIPTOR_TYPE
			     (walk_state->results->results.obj_desc[0]) ==
			     ACPI_DESC_TYPE_OPERAND)
1368 1369
			    && ((walk_state->results->results.obj_desc[0])->
				common.type == ACPI_TYPE_LOCAL_REFERENCE)
L
Len Brown 已提交
1370
			    && ((walk_state->results->results.obj_desc[0])->
1371
				reference.class != ACPI_REFCLASS_INDEX)) {
L
Len Brown 已提交
1372 1373 1374 1375 1376 1377
				status =
				    acpi_ex_resolve_to_value(&walk_state->
							     results->results.
							     obj_desc[0],
							     walk_state);
				if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1378 1379 1380 1381
					return (status);
				}
			}

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

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

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

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

		/* 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:

1413 1414 1415 1416 1417 1418 1419 1420
		/*
		 * 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 已提交
1421

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

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

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

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

		while (walk_state->control_state &&
L
Len Brown 已提交
1434 1435 1436 1437 1438 1439
		       (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 已提交
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
		}

		/* 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 已提交
1450 1451
		walk_state->aml_last_while =
		    walk_state->control_state->control.package_end;
L
Linus Torvalds 已提交
1452 1453 1454 1455 1456

		/* Return status depending on opcode */

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

	default:

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

		status = AE_AML_BAD_OPCODE;
		break;
	}

	return (status);
}