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

/*
B
Bob Moore 已提交
9
 * Copyright (C) 2000 - 2006, R. Byron Moore
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 46 47 48 49 50 51 52 53
 * 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>
#include <acpi/acparser.h>
#include <acpi/amlcode.h>
#include <acpi/acdispat.h>
#include <acpi/acinterp.h>
#include <acpi/acnamesp.h>
#include <acpi/acevents.h>

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

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

static acpi_status
L
Len Brown 已提交
63 64 65 66 67 68
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 已提交
69 70

/*******************************************************************************
L
Linus Torvalds 已提交
71 72 73
 *
 * FUNCTION:    acpi_ds_execute_arguments
 *
R
Robert Moore 已提交
74 75
 * PARAMETERS:  Node                - Object NS node
 *              scope_node          - Parent NS node
L
Linus Torvalds 已提交
76 77 78 79 80 81 82
 *              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 已提交
83
 ******************************************************************************/
L
Linus Torvalds 已提交
84

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

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

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

	/* 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 已提交
110
	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
L
Linus Torvalds 已提交
111
	if (!walk_state) {
112 113
		status = AE_NO_MEMORY;
		goto cleanup;
L
Linus Torvalds 已提交
114 115
	}

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

	/* 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 已提交
130 131
	status = acpi_ps_parse_aml(walk_state);
	if (ACPI_FAILURE(status)) {
132
		goto cleanup;
L
Linus Torvalds 已提交
133 134 135 136 137
	}

	/* Get and init the Op created above */

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

	/* Evaluate the deferred arguments */

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

	op->common.node = scope_node;

	/* Create and initialize a new parser state */

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

	/* Execute the opcode and arguments */

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

	/* Mark this execution as a deferred opcode */

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

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

R
Robert Moore 已提交
176
/*******************************************************************************
L
Linus Torvalds 已提交
177 178 179 180 181 182 183 184 185 186
 *
 * 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 已提交
187
 ******************************************************************************/
L
Linus Torvalds 已提交
188 189

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

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

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

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

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

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

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

L
Len Brown 已提交
214 215 216 217
	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 已提交
218 219
}

R
Robert Moore 已提交
220
/*******************************************************************************
L
Linus Torvalds 已提交
221 222 223 224 225 226 227 228 229 230
 *
 * 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 已提交
231
 ******************************************************************************/
L
Linus Torvalds 已提交
232

L
Len Brown 已提交
233
acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
L
Linus Torvalds 已提交
234
{
L
Len Brown 已提交
235 236
	struct acpi_namespace_node *node;
	acpi_status status;
L
Linus Torvalds 已提交
237

B
Bob Moore 已提交
238
	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
L
Linus Torvalds 已提交
239 240

	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
L
Len Brown 已提交
241
		return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
242 243 244 245 246 247
	}

	/* Get the Buffer node */

	node = obj_desc->buffer.node;
	if (!node) {
B
Bob Moore 已提交
248 249 250
		ACPI_ERROR((AE_INFO,
			    "No pointer back to NS node in buffer obj %p",
			    obj_desc));
L
Len Brown 已提交
251
		return_ACPI_STATUS(AE_AML_INTERNAL);
L
Linus Torvalds 已提交
252 253
	}

L
Len Brown 已提交
254
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
L
Linus Torvalds 已提交
255 256 257

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

L
Len Brown 已提交
258 259 260 261
	status = acpi_ds_execute_arguments(node, node,
					   obj_desc->buffer.aml_length,
					   obj_desc->buffer.aml_start);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
262 263
}

R
Robert Moore 已提交
264
/*******************************************************************************
L
Linus Torvalds 已提交
265 266 267 268 269 270 271 272 273 274
 *
 * 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 已提交
275
 ******************************************************************************/
L
Linus Torvalds 已提交
276

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

B
Bob Moore 已提交
282
	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
L
Linus Torvalds 已提交
283 284

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

	/* Get the Package node */

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

L
Len Brown 已提交
298
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
L
Linus Torvalds 已提交
299 300 301

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

L
Len Brown 已提交
302 303 304 305
	status = acpi_ds_execute_arguments(node, node,
					   obj_desc->package.aml_length,
					   obj_desc->package.aml_start);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
}

/*****************************************************************************
 *
 * 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 已提交
321
acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
L
Linus Torvalds 已提交
322
{
L
Len Brown 已提交
323 324 325
	struct acpi_namespace_node *node;
	acpi_status status;
	union acpi_operand_object *extra_desc;
L
Linus Torvalds 已提交
326

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

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

L
Len Brown 已提交
333
	extra_desc = acpi_ns_get_secondary_object(obj_desc);
L
Linus Torvalds 已提交
334
	if (!extra_desc) {
L
Len Brown 已提交
335
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
336 337 338 339 340 341
	}

	/* Get the Region node */

	node = obj_desc->region.node;

L
Len Brown 已提交
342 343
	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
			(ACPI_TYPE_REGION, node, NULL));
L
Linus Torvalds 已提交
344

B
Bob Moore 已提交
345
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
L
Len Brown 已提交
346 347
			  acpi_ut_get_node_name(node),
			  extra_desc->extra.aml_start));
L
Linus Torvalds 已提交
348 349 350

	/* Execute the argument AML */

L
Len Brown 已提交
351 352 353
	status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node),
					   extra_desc->extra.aml_length,
					   extra_desc->extra.aml_start);
B
Bob Moore 已提交
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
	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);
	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 已提交
376
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
377 378
}

R
Robert Moore 已提交
379
/*******************************************************************************
L
Linus Torvalds 已提交
380 381 382
 *
 * FUNCTION:    acpi_ds_initialize_region
 *
R
Robert Moore 已提交
383
 * PARAMETERS:  obj_handle      - Region namespace node
L
Linus Torvalds 已提交
384 385 386 387 388
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Front end to ev_initialize_region
 *
R
Robert Moore 已提交
389
 ******************************************************************************/
L
Linus Torvalds 已提交
390

L
Len Brown 已提交
391
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
L
Linus Torvalds 已提交
392
{
L
Len Brown 已提交
393 394
	union acpi_operand_object *obj_desc;
	acpi_status status;
L
Linus Torvalds 已提交
395

L
Len Brown 已提交
396
	obj_desc = acpi_ns_get_attached_object(obj_handle);
L
Linus Torvalds 已提交
397 398 399

	/* Namespace is NOT locked */

L
Len Brown 已提交
400
	status = acpi_ev_initialize_region(obj_desc, FALSE);
L
Linus Torvalds 已提交
401 402 403
	return (status);
}

R
Robert Moore 已提交
404
/*******************************************************************************
L
Linus Torvalds 已提交
405 406 407 408 409 410 411
 *
 * 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 已提交
412 413
 *              length_desc     - Length of field (CREATE_FIELD_OP only)
 *              result_desc     - Where to store the result
L
Linus Torvalds 已提交
414 415 416 417 418
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform actual initialization of a buffer field
 *
R
Robert Moore 已提交
419
 ******************************************************************************/
L
Linus Torvalds 已提交
420

R
Robert Moore 已提交
421
static acpi_status
L
Len Brown 已提交
422 423 424 425 426 427
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 已提交
428
{
L
Len Brown 已提交
429 430 431 432 433
	u32 offset;
	u32 bit_offset;
	u32 bit_count;
	u8 field_flags;
	acpi_status status;
L
Linus Torvalds 已提交
434

B
Bob Moore 已提交
435
	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
L
Linus Torvalds 已提交
436 437 438

	/* Host object must be a Buffer */

L
Len Brown 已提交
439
	if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) {
B
Bob Moore 已提交
440 441 442
		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 已提交
443 444 445 446 447 448 449 450 451 452

		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 已提交
453
	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
B
Bob Moore 已提交
454 455 456 457
		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 已提交
458 459 460 461 462 463 464 465 466 467 468 469 470 471 472

		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 已提交
473
		field_flags = AML_FIELD_ACCESS_BYTE;
L
Linus Torvalds 已提交
474
		bit_offset = offset;
L
Len Brown 已提交
475
		bit_count = (u32) length_desc->integer.value;
R
Robert Moore 已提交
476 477 478 479

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

		if (bit_count == 0) {
B
Bob Moore 已提交
480
			ACPI_ERROR((AE_INFO,
B
Bob Moore 已提交
481
				    "Attempt to CreateField of length zero"));
R
Robert Moore 已提交
482 483 484
			status = AE_AML_OPERAND_VALUE;
			goto cleanup;
		}
L
Linus Torvalds 已提交
485 486 487 488 489 490 491
		break;

	case AML_CREATE_BIT_FIELD_OP:

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

		bit_offset = offset;
L
Len Brown 已提交
492
		bit_count = 1;
L
Linus Torvalds 已提交
493 494 495 496 497 498 499 500
		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 已提交
501
		bit_count = 8;
L
Linus Torvalds 已提交
502 503 504 505 506 507 508 509
		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 已提交
510
		bit_count = 16;
L
Linus Torvalds 已提交
511 512 513 514 515 516 517 518
		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 已提交
519
		bit_count = 32;
L
Linus Torvalds 已提交
520 521 522 523 524 525 526 527
		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 已提交
528
		bit_count = 64;
L
Linus Torvalds 已提交
529 530 531 532 533
		field_flags = AML_FIELD_ACCESS_QWORD;
		break;

	default:

B
Bob Moore 已提交
534 535
		ACPI_ERROR((AE_INFO,
			    "Unknown field creation opcode %02x", aml_opcode));
L
Linus Torvalds 已提交
536 537 538 539 540 541
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

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

L
Len Brown 已提交
542
	if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {
B
Bob Moore 已提交
543 544 545 546 547 548
		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 已提交
549 550 551 552 553 554
		status = AE_AML_BUFFER_LIMIT;
		goto cleanup;
	}

	/*
	 * Initialize areas of the field object that are common to all fields
R
Robert Moore 已提交
555 556
	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
L
Linus Torvalds 已提交
557
	 */
L
Len Brown 已提交
558 559 560
	status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
						  bit_offset, bit_count);
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
561 562 563 564 565 566 567
		goto cleanup;
	}

	obj_desc->buffer_field.buffer_obj = buffer_desc;

	/* Reference count for buffer_desc inherits obj_desc count */

R
Robert Moore 已提交
568
	buffer_desc->common.reference_count = (u16)
L
Len Brown 已提交
569 570
	    (buffer_desc->common.reference_count +
	     obj_desc->common.reference_count);
L
Linus Torvalds 已提交
571

L
Len Brown 已提交
572
      cleanup:
L
Linus Torvalds 已提交
573 574 575

	/* Always delete the operands */

L
Len Brown 已提交
576 577
	acpi_ut_remove_reference(offset_desc);
	acpi_ut_remove_reference(buffer_desc);
L
Linus Torvalds 已提交
578 579

	if (aml_opcode == AML_CREATE_FIELD_OP) {
L
Len Brown 已提交
580
		acpi_ut_remove_reference(length_desc);
L
Linus Torvalds 已提交
581 582 583 584
	}

	/* On failure, delete the result descriptor */

L
Len Brown 已提交
585 586 587
	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
	} else {
L
Linus Torvalds 已提交
588 589 590 591 592
		/* Now the address and length are valid for this buffer_field */

		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
	}

L
Len Brown 已提交
593
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
594 595
}

R
Robert Moore 已提交
596
/*******************************************************************************
L
Linus Torvalds 已提交
597 598 599 600 601 602 603 604 605 606 607
 *
 * 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 已提交
608
 ******************************************************************************/
L
Linus Torvalds 已提交
609 610

acpi_status
L
Len Brown 已提交
611 612
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
L
Linus Torvalds 已提交
613
{
L
Len Brown 已提交
614 615 616 617
	acpi_status status;
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
L
Linus Torvalds 已提交
618

B
Bob Moore 已提交
619
	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
L
Linus Torvalds 已提交
620 621 622 623 624

	/*
	 * This is where we evaluate the address and length fields of the
	 * create_xxx_field declaration
	 */
L
Len Brown 已提交
625
	node = op->common.node;
L
Linus Torvalds 已提交
626 627 628 629 630 631 632

	/* 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 已提交
633 634 635
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
636 637
	}

L
Len Brown 已提交
638
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
639
	if (!obj_desc) {
L
Len Brown 已提交
640
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
641 642 643 644
	}

	/* Resolve the operands */

L
Len Brown 已提交
645 646
	status = acpi_ex_resolve_operands(op->common.aml_opcode,
					  ACPI_WALK_OPERANDS, walk_state);
L
Linus Torvalds 已提交
647

L
Len Brown 已提交
648 649 650
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
			   acpi_ps_get_opcode_name(op->common.aml_opcode),
			   walk_state->num_operands,
B
Bob Moore 已提交
651
			   "after AcpiExResolveOperands");
L
Linus Torvalds 已提交
652

L
Len Brown 已提交
653
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
654 655 656
		ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)",
			    acpi_ps_get_opcode_name(op->common.aml_opcode),
			    status));
L
Linus Torvalds 已提交
657

L
Len Brown 已提交
658
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
659 660 661 662 663
	}

	/* Initialize the Buffer Field */

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

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

L
Len Brown 已提交
667 668 669 670 671 672 673
		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 已提交
674 675
		/* All other, create_xxx_field opcodes */

L
Len Brown 已提交
676 677 678 679 680
		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 已提交
681 682
	}

L
Len Brown 已提交
683
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
684 685
}

R
Robert Moore 已提交
686
/*******************************************************************************
L
Linus Torvalds 已提交
687 688 689 690 691 692 693 694 695 696 697
 *
 * 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 已提交
698
 ******************************************************************************/
L
Linus Torvalds 已提交
699 700

acpi_status
L
Len Brown 已提交
701 702
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
L
Linus Torvalds 已提交
703
{
L
Len Brown 已提交
704 705 706 707 708
	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 已提交
709

B
Bob Moore 已提交
710
	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
L
Linus Torvalds 已提交
711 712

	/*
R
Robert Moore 已提交
713 714
	 * This is where we evaluate the address and length fields of the
	 * op_region declaration
L
Linus Torvalds 已提交
715
	 */
L
Len Brown 已提交
716
	node = op->common.node;
L
Linus Torvalds 已提交
717 718 719 720 721 722 723 724 725 726 727

	/* 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 已提交
728 729 730
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
731 732 733 734
	}

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

L
Len Brown 已提交
735 736 737 738
	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 已提交
739 740
	}

L
Len Brown 已提交
741 742
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
			   acpi_ps_get_opcode_name(op->common.aml_opcode),
B
Bob Moore 已提交
743
			   1, "after AcpiExResolveOperands");
L
Linus Torvalds 已提交
744

L
Len Brown 已提交
745
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
746
	if (!obj_desc) {
L
Len Brown 已提交
747
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
748 749 750 751 752 753 754 755 756
	}

	/*
	 * 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 已提交
757
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
758 759 760 761 762 763 764

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

R
Robert Moore 已提交
765
	obj_desc->region.address = (acpi_physical_address)
L
Len Brown 已提交
766 767
	    operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
768

B
Bob Moore 已提交
769
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
L
Len Brown 已提交
770 771 772
			  obj_desc,
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
			  obj_desc->region.length));
L
Linus Torvalds 已提交
773 774 775 776 777

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

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

L
Len Brown 已提交
778
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
779 780
}

R
Robert Moore 已提交
781
/*******************************************************************************
L
Linus Torvalds 已提交
782 783 784 785 786 787 788 789 790 791 792 793
 *
 * 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 已提交
794
 ******************************************************************************/
L
Linus Torvalds 已提交
795 796

acpi_status
L
Len Brown 已提交
797 798 799
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 已提交
800
{
L
Len Brown 已提交
801 802 803
	acpi_status status;
	union acpi_operand_object *arg_desc;
	u32 length;
L
Linus Torvalds 已提交
804

B
Bob Moore 已提交
805
	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
L
Linus Torvalds 已提交
806 807 808

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

L
Len Brown 已提交
809 810 811
	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
812 813
	}

L
Len Brown 已提交
814 815 816 817 818 819
	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 已提交
820 821 822 823
	}

	/* Extract length operand */

L
Len Brown 已提交
824
	arg_desc = walk_state->operands[walk_state->num_operands - 1];
L
Linus Torvalds 已提交
825 826 827 828
	length = (u32) arg_desc->integer.value;

	/* Cleanup for length operand */

L
Len Brown 已提交
829 830 831
	status = acpi_ds_obj_stack_pop(1, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
832 833
	}

L
Len Brown 已提交
834
	acpi_ut_remove_reference(arg_desc);
L
Linus Torvalds 已提交
835 836 837 838 839 840 841

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

L
Len Brown 已提交
842 843 844
		status =
		    acpi_ds_build_internal_buffer_obj(walk_state, op, length,
						      &obj_desc);
L
Linus Torvalds 已提交
845 846 847 848 849
		break;

	case AML_PACKAGE_OP:
	case AML_VAR_PACKAGE_OP:

L
Len Brown 已提交
850 851 852
		status =
		    acpi_ds_build_internal_package_obj(walk_state, op, length,
						       &obj_desc);
L
Linus Torvalds 已提交
853 854 855
		break;

	default:
L
Len Brown 已提交
856
		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
L
Linus Torvalds 已提交
857 858
	}

L
Len Brown 已提交
859
	if (ACPI_SUCCESS(status)) {
L
Linus Torvalds 已提交
860
		/*
R
Robert Moore 已提交
861
		 * Return the object in the walk_state, unless the parent is a package -
L
Linus Torvalds 已提交
862 863 864 865
		 * in this case, the return object will be stored in the parse tree
		 * for the package.
		 */
		if ((!op->common.parent) ||
L
Len Brown 已提交
866 867 868 869 870
		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
		     (op->common.parent->common.aml_opcode !=
		      AML_VAR_PACKAGE_OP)
		     && (op->common.parent->common.aml_opcode !=
			 AML_NAME_OP))) {
L
Linus Torvalds 已提交
871 872 873 874
			walk_state->result_obj = obj_desc;
		}
	}

L
Len Brown 已提交
875
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892
}

/*******************************************************************************
 *
 * 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 已提交
893 894
acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
			      union acpi_parse_object *op)
L
Linus Torvalds 已提交
895
{
L
Len Brown 已提交
896 897
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
898

B
Bob Moore 已提交
899
	ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
L
Linus Torvalds 已提交
900

L
Len Brown 已提交
901 902
	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
			  op->common.aml_opcode, walk_state));
L
Linus Torvalds 已提交
903 904 905 906 907 908 909 910 911 912

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

		/*
		 * 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 已提交
913
		control_state = acpi_ut_create_control_state();
L
Linus Torvalds 已提交
914 915 916 917 918 919 920 921
		if (!control_state) {
			status = AE_NO_MEMORY;
			break;
		}
		/*
		 * Save a pointer to the predicate for multiple executions
		 * of a loop
		 */
L
Len Brown 已提交
922 923 924 925
		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 已提交
926 927 928 929
		control_state->control.opcode = op->common.aml_opcode;

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

L
Len Brown 已提交
930 931
		acpi_ut_push_generic_state(&walk_state->control_state,
					   control_state);
L
Linus Torvalds 已提交
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
		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 已提交
971 972
acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
			    union acpi_parse_object * op)
L
Linus Torvalds 已提交
973
{
L
Len Brown 已提交
974 975
	acpi_status status = AE_OK;
	union acpi_generic_state *control_state;
L
Linus Torvalds 已提交
976

B
Bob Moore 已提交
977
	ACPI_FUNCTION_NAME(ds_exec_end_control_op);
L
Linus Torvalds 已提交
978 979 980 981

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

L
Len Brown 已提交
982
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
L
Linus Torvalds 已提交
983 984 985 986 987 988

		/*
		 * Save the result of the predicate in case there is an
		 * ELSE to come
		 */
		walk_state->last_predicate =
L
Len Brown 已提交
989
		    (u8) walk_state->control_state->common.value;
L
Linus Torvalds 已提交
990 991 992 993 994

		/*
		 * Pop the control state that was created at the start
		 * of the IF and free it
		 */
L
Len Brown 已提交
995 996 997
		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);
		acpi_ut_delete_generic_state(control_state);
L
Linus Torvalds 已提交
998 999 1000 1001 1002 1003 1004 1005
		break;

	case AML_ELSE_OP:

		break;

	case AML_WHILE_OP:

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

		if (walk_state->control_state->common.value) {
B
Bob Moore 已提交
1009

L
Linus Torvalds 已提交
1010 1011 1012 1013 1014
			/* Predicate was true, go back and evaluate it again! */

			status = AE_CTRL_PENDING;
		}

L
Len Brown 已提交
1015 1016
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[WHILE_OP] termination! Op=%p\n", op));
L
Linus Torvalds 已提交
1017 1018 1019

		/* Pop this control state and free it */

L
Len Brown 已提交
1020 1021
		control_state =
		    acpi_ut_pop_generic_state(&walk_state->control_state);
L
Linus Torvalds 已提交
1022

L
Len Brown 已提交
1023 1024 1025
		walk_state->aml_last_while =
		    control_state->control.aml_predicate_start;
		acpi_ut_delete_generic_state(control_state);
L
Linus Torvalds 已提交
1026 1027 1028 1029
		break;

	case AML_RETURN_OP:

L
Len Brown 已提交
1030 1031 1032
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "[RETURN_OP] Op=%p Arg=%p\n", op,
				  op->common.value.arg));
L
Linus Torvalds 已提交
1033 1034 1035 1036 1037 1038 1039

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

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

L
Len Brown 已提交
1043
			acpi_ds_clear_implicit_return(walk_state);
L
Linus Torvalds 已提交
1044 1045 1046

			/* Return statement has an immediate operand */

L
Len Brown 已提交
1047 1048 1049 1050
			status =
			    acpi_ds_create_operands(walk_state,
						    op->common.value.arg);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1051 1052 1053 1054 1055 1056 1057 1058
				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 已提交
1059 1060 1061 1062
			status =
			    acpi_ex_resolve_to_value(&walk_state->operands[0],
						     walk_state);
			if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1063 1064 1065 1066 1067 1068 1069 1070 1071
				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];
L
Len Brown 已提交
1072 1073
		} else if ((walk_state->results) &&
			   (walk_state->results->results.num_results > 0)) {
B
Bob Moore 已提交
1074

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

L
Len Brown 已提交
1077
			acpi_ds_clear_implicit_return(walk_state);
L
Linus Torvalds 已提交
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087

			/*
			 * 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 已提交
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
			if ((ACPI_GET_DESCRIPTOR_TYPE
			     (walk_state->results->results.obj_desc[0]) ==
			     ACPI_DESC_TYPE_OPERAND)
			    &&
			    (ACPI_GET_OBJECT_TYPE
			     (walk_state->results->results.obj_desc[0]) ==
			     ACPI_TYPE_LOCAL_REFERENCE)
			    && ((walk_state->results->results.obj_desc[0])->
				reference.opcode != AML_INDEX_OP)) {
				status =
				    acpi_ex_resolve_to_value(&walk_state->
							     results->results.
							     obj_desc[0],
							     walk_state);
				if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
1103 1104 1105 1106
					return (status);
				}
			}

L
Len Brown 已提交
1107 1108 1109
			walk_state->return_desc =
			    walk_state->results->results.obj_desc[0];
		} else {
L
Linus Torvalds 已提交
1110 1111 1112
			/* No return operand */

			if (walk_state->num_operands) {
L
Len Brown 已提交
1113 1114
				acpi_ut_remove_reference(walk_state->
							 operands[0]);
L
Linus Torvalds 已提交
1115 1116
			}

L
Len Brown 已提交
1117 1118 1119
			walk_state->operands[0] = NULL;
			walk_state->num_operands = 0;
			walk_state->return_desc = NULL;
L
Linus Torvalds 已提交
1120 1121
		}

L
Len Brown 已提交
1122
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
B
Bob Moore 已提交
1123
				  "Completed RETURN_OP State=%p, RetVal=%p\n",
L
Len Brown 已提交
1124
				  walk_state, walk_state->return_desc));
L
Linus Torvalds 已提交
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139

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

		/* Call up to the OS service layer to handle this */

L
Len Brown 已提交
1140 1141 1142
		status =
		    acpi_os_signal(ACPI_SIGNAL_BREAKPOINT,
				   "Executed AML Breakpoint opcode");
L
Linus Torvalds 已提交
1143 1144 1145 1146 1147 1148

		/* If and when it returns, all done. */

		break;

	case AML_BREAK_OP:
L
Len Brown 已提交
1149
	case AML_CONTINUE_OP:	/* ACPI 2.0 */
L
Linus Torvalds 已提交
1150 1151 1152 1153

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

		while (walk_state->control_state &&
L
Len Brown 已提交
1154 1155 1156 1157 1158 1159
		       (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 已提交
1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
		}

		/* 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 已提交
1170 1171
		walk_state->aml_last_while =
		    walk_state->control_state->control.package_end;
L
Linus Torvalds 已提交
1172 1173 1174 1175 1176

		/* Return status depending on opcode */

		if (op->common.aml_opcode == AML_BREAK_OP) {
			status = AE_CTRL_BREAK;
L
Len Brown 已提交
1177
		} else {
L
Linus Torvalds 已提交
1178 1179 1180 1181 1182 1183
			status = AE_CTRL_CONTINUE;
		}
		break;

	default:

B
Bob Moore 已提交
1184 1185
		ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p",
			    op->common.aml_opcode, op));
L
Linus Torvalds 已提交
1186 1187 1188 1189 1190 1191 1192

		status = AE_AML_BAD_OPCODE;
		break;
	}

	return (status);
}