dsopcode.c 38.4 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
 *
 *****************************************************************************/

/*
L
Len Brown 已提交
9
 * Copyright (C) 2000 - 2008, 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 400
	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 已提交
401 402
}

R
Robert Moore 已提交
403
/*******************************************************************************
L
Linus Torvalds 已提交
404 405 406
 *
 * FUNCTION:    acpi_ds_initialize_region
 *
R
Robert Moore 已提交
407
 * PARAMETERS:  obj_handle      - Region namespace node
L
Linus Torvalds 已提交
408 409 410 411 412
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Front end to ev_initialize_region
 *
R
Robert Moore 已提交
413
 ******************************************************************************/
L
Linus Torvalds 已提交
414

L
Len Brown 已提交
415
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
L
Linus Torvalds 已提交
416
{
L
Len Brown 已提交
417 418
	union acpi_operand_object *obj_desc;
	acpi_status status;
L
Linus Torvalds 已提交
419

L
Len Brown 已提交
420
	obj_desc = acpi_ns_get_attached_object(obj_handle);
L
Linus Torvalds 已提交
421 422 423

	/* Namespace is NOT locked */

L
Len Brown 已提交
424
	status = acpi_ev_initialize_region(obj_desc, FALSE);
L
Linus Torvalds 已提交
425 426 427
	return (status);
}

R
Robert Moore 已提交
428
/*******************************************************************************
L
Linus Torvalds 已提交
429 430 431 432 433 434 435
 *
 * 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 已提交
436 437
 *              length_desc     - Length of field (CREATE_FIELD_OP only)
 *              result_desc     - Where to store the result
L
Linus Torvalds 已提交
438 439 440 441 442
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform actual initialization of a buffer field
 *
R
Robert Moore 已提交
443
 ******************************************************************************/
L
Linus Torvalds 已提交
444

R
Robert Moore 已提交
445
static acpi_status
L
Len Brown 已提交
446 447 448 449 450 451
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 已提交
452
{
L
Len Brown 已提交
453 454 455 456 457
	u32 offset;
	u32 bit_offset;
	u32 bit_count;
	u8 field_flags;
	acpi_status status;
L
Linus Torvalds 已提交
458

B
Bob Moore 已提交
459
	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
L
Linus Torvalds 已提交
460 461 462

	/* Host object must be a Buffer */

463
	if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
B
Bob Moore 已提交
464 465 466
		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 已提交
467 468 469 470 471 472 473 474 475 476

		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 已提交
477
	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
B
Bob Moore 已提交
478 479 480 481
		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 已提交
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496

		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 已提交
497
		field_flags = AML_FIELD_ACCESS_BYTE;
L
Linus Torvalds 已提交
498
		bit_offset = offset;
L
Len Brown 已提交
499
		bit_count = (u32) length_desc->integer.value;
R
Robert Moore 已提交
500 501 502 503

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

		if (bit_count == 0) {
B
Bob Moore 已提交
504
			ACPI_ERROR((AE_INFO,
B
Bob Moore 已提交
505
				    "Attempt to CreateField of length zero"));
R
Robert Moore 已提交
506 507 508
			status = AE_AML_OPERAND_VALUE;
			goto cleanup;
		}
L
Linus Torvalds 已提交
509 510 511 512 513 514 515
		break;

	case AML_CREATE_BIT_FIELD_OP:

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

		bit_offset = offset;
L
Len Brown 已提交
516
		bit_count = 1;
L
Linus Torvalds 已提交
517 518 519 520 521 522 523 524
		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 已提交
525
		bit_count = 8;
L
Linus Torvalds 已提交
526 527 528 529 530 531 532 533
		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 已提交
534
		bit_count = 16;
L
Linus Torvalds 已提交
535 536 537 538 539 540 541 542
		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 已提交
543
		bit_count = 32;
L
Linus Torvalds 已提交
544 545 546 547 548 549 550 551
		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 已提交
552
		bit_count = 64;
L
Linus Torvalds 已提交
553 554 555 556 557
		field_flags = AML_FIELD_ACCESS_QWORD;
		break;

	default:

B
Bob Moore 已提交
558 559
		ACPI_ERROR((AE_INFO,
			    "Unknown field creation opcode %02x", aml_opcode));
L
Linus Torvalds 已提交
560 561 562 563 564 565
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

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

L
Len Brown 已提交
566
	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
B
Bob Moore 已提交
567 568 569 570 571 572
		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 已提交
573 574 575 576 577 578
		status = AE_AML_BUFFER_LIMIT;
		goto cleanup;
	}

	/*
	 * Initialize areas of the field object that are common to all fields
R
Robert Moore 已提交
579 580
	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
L
Linus Torvalds 已提交
581
	 */
L
Len Brown 已提交
582 583 584
	status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
						  bit_offset, bit_count);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
585 586 587 588 589 590 591
		goto cleanup;
	}

	obj_desc->buffer_field.buffer_obj = buffer_desc;

	/* Reference count for buffer_desc inherits obj_desc count */

R
Robert Moore 已提交
592
	buffer_desc->common.reference_count = (u16)
L
Len Brown 已提交
593 594
	    (buffer_desc->common.reference_count +
	     obj_desc->common.reference_count);
L
Linus Torvalds 已提交
595

L
Len Brown 已提交
596
      cleanup:
L
Linus Torvalds 已提交
597 598 599

	/* Always delete the operands */

L
Len Brown 已提交
600 601
	acpi_ut_remove_reference(offset_desc);
	acpi_ut_remove_reference(buffer_desc);
L
Linus Torvalds 已提交
602 603

	if (aml_opcode == AML_CREATE_FIELD_OP) {
L
Len Brown 已提交
604
		acpi_ut_remove_reference(length_desc);
L
Linus Torvalds 已提交
605 606 607 608
	}

	/* On failure, delete the result descriptor */

L
Len Brown 已提交
609 610 611
	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
	} else {
L
Linus Torvalds 已提交
612 613 614 615 616
		/* Now the address and length are valid for this buffer_field */

		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
	}

L
Len Brown 已提交
617
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
618 619
}

R
Robert Moore 已提交
620
/*******************************************************************************
L
Linus Torvalds 已提交
621 622 623 624 625 626 627 628 629 630 631
 *
 * 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 已提交
632
 ******************************************************************************/
L
Linus Torvalds 已提交
633 634

acpi_status
L
Len Brown 已提交
635 636
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
L
Linus Torvalds 已提交
637
{
L
Len Brown 已提交
638 639 640 641
	acpi_status status;
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
L
Linus Torvalds 已提交
642

B
Bob Moore 已提交
643
	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
L
Linus Torvalds 已提交
644 645 646 647 648

	/*
	 * This is where we evaluate the address and length fields of the
	 * create_xxx_field declaration
	 */
L
Len Brown 已提交
649
	node = op->common.node;
L
Linus Torvalds 已提交
650 651 652 653 654 655 656

	/* 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 已提交
657 658 659
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
660 661
	}

L
Len Brown 已提交
662
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
663
	if (!obj_desc) {
L
Len Brown 已提交
664
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
665 666 667 668
	}

	/* Resolve the operands */

L
Len Brown 已提交
669 670 671
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
672 673 674
		ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
			    acpi_ps_get_opcode_name(op->common.aml_opcode),
			    status));
L
Linus Torvalds 已提交
675

L
Len Brown 已提交
676
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
677 678 679 680 681
	}

	/* Initialize the Buffer Field */

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

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

L
Len Brown 已提交
685 686 687 688 689 690 691
		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 已提交
692 693
		/* All other, create_xxx_field opcodes */

L
Len Brown 已提交
694 695 696 697 698
		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 已提交
699 700
	}

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

R
Robert Moore 已提交
704
/*******************************************************************************
L
Linus Torvalds 已提交
705 706 707 708 709 710 711 712 713 714 715
 *
 * 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 已提交
716
 ******************************************************************************/
L
Linus Torvalds 已提交
717 718

acpi_status
L
Len Brown 已提交
719 720
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
L
Linus Torvalds 已提交
721
{
L
Len Brown 已提交
722 723 724 725 726
	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 已提交
727

B
Bob Moore 已提交
728
	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
L
Linus Torvalds 已提交
729 730

	/*
R
Robert Moore 已提交
731 732
	 * This is where we evaluate the address and length fields of the
	 * op_region declaration
L
Linus Torvalds 已提交
733
	 */
L
Len Brown 已提交
734
	node = op->common.node;
L
Linus Torvalds 已提交
735 736 737 738 739 740 741 742 743 744 745

	/* 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 已提交
746 747 748
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
749 750 751 752
	}

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

L
Len Brown 已提交
753 754 755 756
	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 已提交
757 758
	}

L
Len Brown 已提交
759
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
760
	if (!obj_desc) {
L
Len Brown 已提交
761
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
762 763 764 765 766 767 768 769 770
	}

	/*
	 * 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 已提交
771
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
772 773 774 775 776 777 778

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

R
Robert Moore 已提交
779
	obj_desc->region.address = (acpi_physical_address)
L
Len Brown 已提交
780 781
	    operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
782

B
Bob Moore 已提交
783
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
L
Len Brown 已提交
784
			  obj_desc,
785
			  ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),
L
Len Brown 已提交
786
			  obj_desc->region.length));
L
Linus Torvalds 已提交
787 788 789 790 791

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

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

L
Len Brown 已提交
792
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
793 794
}

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
/*******************************************************************************
 *
 * 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;
818
	u32 table_index;
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 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
	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 已提交
893
/*******************************************************************************
L
Linus Torvalds 已提交
894 895 896 897 898 899 900 901 902 903 904 905
 *
 * 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 已提交
906
 ******************************************************************************/
L
Linus Torvalds 已提交
907 908

acpi_status
L
Len Brown 已提交
909 910 911
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 已提交
912
{
L
Len Brown 已提交
913 914 915
	acpi_status status;
	union acpi_operand_object *arg_desc;
	u32 length;
L
Linus Torvalds 已提交
916

B
Bob Moore 已提交
917
	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
L
Linus Torvalds 已提交
918 919 920

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

921 922 923 924 925 926
	/*
	 * 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 已提交
927 928 929
	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
930 931
	}

L
Len Brown 已提交
932 933 934 935 936 937
	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 已提交
938 939 940 941
	}

	/* Extract length operand */

L
Len Brown 已提交
942
	arg_desc = walk_state->operands[walk_state->num_operands - 1];
L
Linus Torvalds 已提交
943 944 945 946
	length = (u32) arg_desc->integer.value;

	/* Cleanup for length operand */

L
Len Brown 已提交
947 948 949
	status = acpi_ds_obj_stack_pop(1, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
950 951
	}

L
Len Brown 已提交
952
	acpi_ut_remove_reference(arg_desc);
L
Linus Torvalds 已提交
953 954 955 956 957 958 959

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

L
Len Brown 已提交
960 961 962
		status =
		    acpi_ds_build_internal_buffer_obj(walk_state, op, length,
						      &obj_desc);
L
Linus Torvalds 已提交
963 964 965 966 967
		break;

	case AML_PACKAGE_OP:
	case AML_VAR_PACKAGE_OP:

L
Len Brown 已提交
968 969 970
		status =
		    acpi_ds_build_internal_package_obj(walk_state, op, length,
						       &obj_desc);
L
Linus Torvalds 已提交
971 972 973
		break;

	default:
L
Len Brown 已提交
974
		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
L
Linus Torvalds 已提交
975 976
	}

L
Len Brown 已提交
977
	if (ACPI_SUCCESS(status)) {
L
Linus Torvalds 已提交
978
		/*
R
Robert Moore 已提交
979
		 * Return the object in the walk_state, unless the parent is a package -
L
Linus Torvalds 已提交
980 981 982 983
		 * in this case, the return object will be stored in the parse tree
		 * for the package.
		 */
		if ((!op->common.parent) ||
L
Len Brown 已提交
984 985 986
		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
		     (op->common.parent->common.aml_opcode !=
		      AML_VAR_PACKAGE_OP)
L
Len Brown 已提交
987
		     && (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
L
Linus Torvalds 已提交
988 989 990 991
			walk_state->result_obj = obj_desc;
		}
	}

L
Len Brown 已提交
992
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
993 994
}

995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 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
/*******************************************************************************
 *
 * 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);
	}

1057 1058
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
	/*
	 * 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 已提交
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
/*******************************************************************************
 *
 * 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 已提交
1108 1109
acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
			      union acpi_parse_object *op)
L
Linus Torvalds 已提交
1110
{
L
Len Brown 已提交
1111 1112
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
1113

B
Bob Moore 已提交
1114
	ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
L
Linus Torvalds 已提交
1115

L
Len Brown 已提交
1116 1117
	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
			  op->common.aml_opcode, walk_state));
L
Linus Torvalds 已提交
1118 1119 1120 1121

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

1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
		/*
		 * 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 已提交
1142 1143 1144 1145 1146
		/*
		 * 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 已提交
1147
		control_state = acpi_ut_create_control_state();
L
Linus Torvalds 已提交
1148 1149 1150 1151 1152 1153 1154 1155
		if (!control_state) {
			status = AE_NO_MEMORY;
			break;
		}
		/*
		 * Save a pointer to the predicate for multiple executions
		 * of a loop
		 */
L
Len Brown 已提交
1156 1157 1158 1159
		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 已提交
1160 1161 1162 1163
		control_state->control.opcode = op->common.aml_opcode;

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

L
Len Brown 已提交
1164 1165
		acpi_ut_push_generic_state(&walk_state->control_state,
					   control_state);
L
Linus Torvalds 已提交
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
		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 已提交
1205 1206
acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
			    union acpi_parse_object * op)
L
Linus Torvalds 已提交
1207
{
L
Len Brown 已提交
1208 1209
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
1210

B
Bob Moore 已提交
1211
	ACPI_FUNCTION_NAME(ds_exec_end_control_op);
L
Linus Torvalds 已提交
1212 1213 1214 1215

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

L
Len Brown 已提交
1216
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
L
Linus Torvalds 已提交
1217 1218 1219 1220 1221 1222

		/*
		 * Save the result of the predicate in case there is an
		 * ELSE to come
		 */
		walk_state->last_predicate =
L
Len Brown 已提交
1223
		    (u8) walk_state->control_state->common.value;
L
Linus Torvalds 已提交
1224 1225 1226 1227 1228

		/*
		 * Pop the control state that was created at the start
		 * of the IF and free it
		 */
L
Len Brown 已提交
1229 1230 1231
		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);
		acpi_ut_delete_generic_state(control_state);
L
Linus Torvalds 已提交
1232 1233 1234 1235 1236 1237 1238 1239
		break;

	case AML_ELSE_OP:

		break;

	case AML_WHILE_OP:

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

1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
		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 已提交
1259

1260 1261 1262 1263
			/*
			 * Go back and evaluate the predicate and maybe execute the loop
			 * another time
			 */
L
Linus Torvalds 已提交
1264
			status = AE_CTRL_PENDING;
1265
			walk_state->aml_last_while =
1266
			    control_state->control.aml_predicate_start;
1267
			break;
L
Linus Torvalds 已提交
1268 1269
		}

1270 1271
		/* Predicate was false, terminate this while loop */

L
Len Brown 已提交
1272 1273
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[WHILE_OP] termination! Op=%p\n", op));
L
Linus Torvalds 已提交
1274 1275 1276

		/* Pop this control state and free it */

L
Len Brown 已提交
1277 1278 1279
		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);
		acpi_ut_delete_generic_state(control_state);
L
Linus Torvalds 已提交
1280 1281 1282 1283
		break;

	case AML_RETURN_OP:

L
Len Brown 已提交
1284 1285 1286
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[RETURN_OP] Op=%p Arg=%p\n", op,
				  op->common.value.arg));
L
Linus Torvalds 已提交
1287 1288 1289 1290 1291 1292 1293

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

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

L
Len Brown 已提交
1297
			acpi_ds_clear_implicit_return(walk_state);
L
Linus Torvalds 已提交
1298 1299 1300

			/* Return statement has an immediate operand */

L
Len Brown 已提交
1301 1302 1303 1304
			status =
			    acpi_ds_create_operands(walk_state,
						    op->common.value.arg);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1305 1306 1307 1308 1309 1310 1311 1312
				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 已提交
1313 1314 1315 1316
			status =
			    acpi_ex_resolve_to_value(&walk_state->operands[0],
						     walk_state);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1317 1318 1319 1320 1321 1322 1323 1324 1325
				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];
1326
		} else if (walk_state->result_count) {
B
Bob Moore 已提交
1327

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

L
Len Brown 已提交
1330
			acpi_ds_clear_implicit_return(walk_state);
L
Linus Torvalds 已提交
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340

			/*
			 * 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 已提交
1341 1342 1343
			if ((ACPI_GET_DESCRIPTOR_TYPE
			     (walk_state->results->results.obj_desc[0]) ==
			     ACPI_DESC_TYPE_OPERAND)
1344 1345
			    && ((walk_state->results->results.obj_desc[0])->
				common.type == ACPI_TYPE_LOCAL_REFERENCE)
L
Len Brown 已提交
1346
			    && ((walk_state->results->results.obj_desc[0])->
1347
				reference.class != ACPI_REFCLASS_INDEX)) {
L
Len Brown 已提交
1348 1349 1350 1351 1352 1353
				status =
				    acpi_ex_resolve_to_value(&walk_state->
							     results->results.
							     obj_desc[0],
							     walk_state);
				if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1354 1355 1356 1357
					return (status);
				}
			}

L
Len Brown 已提交
1358 1359 1360
			walk_state->return_desc =
			    walk_state->results->results.obj_desc[0];
		} else {
L
Linus Torvalds 已提交
1361 1362 1363
			/* No return operand */

			if (walk_state->num_operands) {
L
Len Brown 已提交
1364 1365
				acpi_ut_remove_reference(walk_state->
							 operands[0]);
L
Linus Torvalds 已提交
1366 1367
			}

L
Len Brown 已提交
1368 1369 1370
			walk_state->operands[0] = NULL;
			walk_state->num_operands = 0;
			walk_state->return_desc = NULL;
L
Linus Torvalds 已提交
1371 1372
		}

L
Len Brown 已提交
1373
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
B
Bob Moore 已提交
1374
				  "Completed RETURN_OP State=%p, RetVal=%p\n",
L
Len Brown 已提交
1375
				  walk_state, walk_state->return_desc));
L
Linus Torvalds 已提交
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388

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

1389 1390 1391 1392 1393 1394 1395 1396
		/*
		 * 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 已提交
1397

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

1400 1401
		status = acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
					"Executed AML Breakpoint opcode");
L
Linus Torvalds 已提交
1402 1403 1404
		break;

	case AML_BREAK_OP:
L
Len Brown 已提交
1405
	case AML_CONTINUE_OP:	/* ACPI 2.0 */
L
Linus Torvalds 已提交
1406 1407 1408 1409

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

		while (walk_state->control_state &&
L
Len Brown 已提交
1410 1411 1412 1413 1414 1415
		       (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 已提交
1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
		}

		/* 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 已提交
1426 1427
		walk_state->aml_last_while =
		    walk_state->control_state->control.package_end;
L
Linus Torvalds 已提交
1428 1429 1430 1431 1432

		/* Return status depending on opcode */

		if (op->common.aml_opcode == AML_BREAK_OP) {
			status = AE_CTRL_BREAK;
L
Len Brown 已提交
1433
		} else {
L
Linus Torvalds 已提交
1434 1435 1436 1437 1438 1439
			status = AE_CTRL_CONTINUE;
		}
		break;

	default:

B
Bob Moore 已提交
1440 1441
		ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p",
			    op->common.aml_opcode, op));
L
Linus Torvalds 已提交
1442 1443 1444 1445 1446 1447 1448

		status = AE_AML_BAD_OPCODE;
		break;
	}

	return (status);
}