dsopcode.c 19.0 KB
Newer Older
E
Erik Schmauss 已提交
1
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
L
Linus Torvalds 已提交
2 3
/******************************************************************************
 *
4
 * Module Name: dsopcode - Dispatcher support for regions and fields
L
Linus Torvalds 已提交
5
 *
6
 * Copyright (C) 2000 - 2018, Intel Corp.
L
Linus Torvalds 已提交
7
 *
E
Erik Schmauss 已提交
8
 *****************************************************************************/
L
Linus Torvalds 已提交
9 10

#include <acpi/acpi.h>
L
Len Brown 已提交
11 12 13 14 15 16 17 18
#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 已提交
19 20

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

R
Robert Moore 已提交
23 24
/* Local prototypes */
static acpi_status
L
Len Brown 已提交
25 26 27 28 29 30
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 已提交
31 32

/*******************************************************************************
L
Linus Torvalds 已提交
33 34 35
 *
 * FUNCTION:    acpi_ds_initialize_region
 *
R
Robert Moore 已提交
36
 * PARAMETERS:  obj_handle      - Region namespace node
L
Linus Torvalds 已提交
37 38 39 40 41
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Front end to ev_initialize_region
 *
R
Robert Moore 已提交
42
 ******************************************************************************/
L
Linus Torvalds 已提交
43

L
Len Brown 已提交
44
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
L
Linus Torvalds 已提交
45
{
L
Len Brown 已提交
46 47
	union acpi_operand_object *obj_desc;
	acpi_status status;
L
Linus Torvalds 已提交
48

L
Len Brown 已提交
49
	obj_desc = acpi_ns_get_attached_object(obj_handle);
L
Linus Torvalds 已提交
50 51 52

	/* Namespace is NOT locked */

53
	status = acpi_ev_initialize_region(obj_desc);
L
Linus Torvalds 已提交
54 55 56
	return (status);
}

R
Robert Moore 已提交
57
/*******************************************************************************
L
Linus Torvalds 已提交
58 59 60 61 62 63 64
 *
 * 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 已提交
65 66
 *              length_desc     - Length of field (CREATE_FIELD_OP only)
 *              result_desc     - Where to store the result
L
Linus Torvalds 已提交
67 68 69 70 71
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Perform actual initialization of a buffer field
 *
R
Robert Moore 已提交
72
 ******************************************************************************/
L
Linus Torvalds 已提交
73

R
Robert Moore 已提交
74
static acpi_status
L
Len Brown 已提交
75 76 77 78 79 80
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 已提交
81
{
L
Len Brown 已提交
82 83 84 85 86
	u32 offset;
	u32 bit_offset;
	u32 bit_count;
	u8 field_flags;
	acpi_status status;
L
Linus Torvalds 已提交
87

B
Bob Moore 已提交
88
	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
L
Linus Torvalds 已提交
89 90 91

	/* Host object must be a Buffer */

92
	if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
B
Bob Moore 已提交
93 94 95
		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 已提交
96 97 98 99 100 101 102 103 104 105

		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 已提交
106
	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
B
Bob Moore 已提交
107 108 109 110
		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 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125

		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 已提交
126
		field_flags = AML_FIELD_ACCESS_BYTE;
L
Linus Torvalds 已提交
127
		bit_offset = offset;
L
Len Brown 已提交
128
		bit_count = (u32) length_desc->integer.value;
R
Robert Moore 已提交
129 130 131 132

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

		if (bit_count == 0) {
B
Bob Moore 已提交
133
			ACPI_ERROR((AE_INFO,
B
Bob Moore 已提交
134
				    "Attempt to CreateField of length zero"));
R
Robert Moore 已提交
135 136 137
			status = AE_AML_OPERAND_VALUE;
			goto cleanup;
		}
L
Linus Torvalds 已提交
138 139 140 141 142 143 144
		break;

	case AML_CREATE_BIT_FIELD_OP:

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

		bit_offset = offset;
L
Len Brown 已提交
145
		bit_count = 1;
L
Linus Torvalds 已提交
146 147 148 149 150 151 152 153
		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 已提交
154
		bit_count = 8;
L
Linus Torvalds 已提交
155 156 157 158 159 160 161 162
		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 已提交
163
		bit_count = 16;
L
Linus Torvalds 已提交
164 165 166 167 168 169 170 171
		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 已提交
172
		bit_count = 32;
L
Linus Torvalds 已提交
173 174 175 176 177 178 179 180
		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 已提交
181
		bit_count = 64;
L
Linus Torvalds 已提交
182 183 184 185 186
		field_flags = AML_FIELD_ACCESS_QWORD;
		break;

	default:

B
Bob Moore 已提交
187
		ACPI_ERROR((AE_INFO,
188 189
			    "Unknown field creation opcode 0x%02X",
			    aml_opcode));
L
Linus Torvalds 已提交
190 191 192 193 194 195
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

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

196
	if ((bit_offset + bit_count) > (8 * (u32)buffer_desc->buffer.length)) {
B
Bob Moore 已提交
197
		ACPI_ERROR((AE_INFO,
198 199 200 201
			    "Field [%4.4s] at bit offset/length %u/%u "
			    "exceeds size of target Buffer (%u bits)",
			    acpi_ut_get_node_name(result_desc), bit_offset,
			    bit_count, 8 * (u32)buffer_desc->buffer.length));
L
Linus Torvalds 已提交
202 203 204 205 206 207
		status = AE_AML_BUFFER_LIMIT;
		goto cleanup;
	}

	/*
	 * Initialize areas of the field object that are common to all fields
R
Robert Moore 已提交
208 209
	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
L
Linus Torvalds 已提交
210
	 */
211 212 213
	status =
	    acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
					     bit_offset, bit_count);
L
Len Brown 已提交
214
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
215 216 217 218 219 220 221
		goto cleanup;
	}

	obj_desc->buffer_field.buffer_obj = buffer_desc;

	/* Reference count for buffer_desc inherits obj_desc count */

R
Robert Moore 已提交
222
	buffer_desc->common.reference_count = (u16)
L
Len Brown 已提交
223 224
	    (buffer_desc->common.reference_count +
	     obj_desc->common.reference_count);
L
Linus Torvalds 已提交
225

226
cleanup:
L
Linus Torvalds 已提交
227 228 229

	/* Always delete the operands */

L
Len Brown 已提交
230 231
	acpi_ut_remove_reference(offset_desc);
	acpi_ut_remove_reference(buffer_desc);
L
Linus Torvalds 已提交
232 233

	if (aml_opcode == AML_CREATE_FIELD_OP) {
L
Len Brown 已提交
234
		acpi_ut_remove_reference(length_desc);
L
Linus Torvalds 已提交
235 236 237 238
	}

	/* On failure, delete the result descriptor */

L
Len Brown 已提交
239 240 241
	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
	} else {
L
Linus Torvalds 已提交
242 243 244 245 246
		/* Now the address and length are valid for this buffer_field */

		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
	}

L
Len Brown 已提交
247
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
248 249
}

R
Robert Moore 已提交
250
/*******************************************************************************
L
Linus Torvalds 已提交
251 252 253 254
 *
 * FUNCTION:    acpi_ds_eval_buffer_field_operands
 *
 * PARAMETERS:  walk_state      - Current walk
255
 *              op              - A valid buffer_field Op object
L
Linus Torvalds 已提交
256 257 258 259 260 261
 *
 * 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 已提交
262
 ******************************************************************************/
L
Linus Torvalds 已提交
263 264

acpi_status
L
Len Brown 已提交
265 266
acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
				   union acpi_parse_object *op)
L
Linus Torvalds 已提交
267
{
L
Len Brown 已提交
268 269 270 271
	acpi_status status;
	union acpi_operand_object *obj_desc;
	struct acpi_namespace_node *node;
	union acpi_parse_object *next_op;
L
Linus Torvalds 已提交
272

B
Bob Moore 已提交
273
	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
L
Linus Torvalds 已提交
274 275 276 277 278

	/*
	 * This is where we evaluate the address and length fields of the
	 * create_xxx_field declaration
	 */
L
Len Brown 已提交
279
	node = op->common.node;
L
Linus Torvalds 已提交
280 281 282 283 284 285 286

	/* 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 已提交
287 288 289
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
290 291
	}

L
Len Brown 已提交
292
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
293
	if (!obj_desc) {
L
Len Brown 已提交
294
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
295 296 297 298
	}

	/* Resolve the operands */

299 300 301
	status =
	    acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
				     walk_state);
L
Len Brown 已提交
302
	if (ACPI_FAILURE(status)) {
303
		ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
B
Bob Moore 已提交
304 305
			    acpi_ps_get_opcode_name(op->common.aml_opcode),
			    status));
L
Linus Torvalds 已提交
306

L
Len Brown 已提交
307
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
308 309 310 311 312
	}

	/* Initialize the Buffer Field */

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

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

L
Len Brown 已提交
316 317 318 319 320 321 322
		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 已提交
323 324
		/* All other, create_xxx_field opcodes */

L
Len Brown 已提交
325 326 327 328 329
		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 已提交
330 331
	}

L
Len Brown 已提交
332
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
333 334
}

R
Robert Moore 已提交
335
/*******************************************************************************
L
Linus Torvalds 已提交
336 337 338 339
 *
 * FUNCTION:    acpi_ds_eval_region_operands
 *
 * PARAMETERS:  walk_state      - Current walk
340
 *              op              - A valid region Op object
L
Linus Torvalds 已提交
341 342 343 344 345 346
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get region address and length
 *              Called from acpi_ds_exec_end_op during op_region parse tree walk
 *
R
Robert Moore 已提交
347
 ******************************************************************************/
L
Linus Torvalds 已提交
348 349

acpi_status
L
Len Brown 已提交
350 351
acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
			     union acpi_parse_object *op)
L
Linus Torvalds 已提交
352
{
L
Len Brown 已提交
353 354 355 356 357
	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 已提交
358

B
Bob Moore 已提交
359
	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
L
Linus Torvalds 已提交
360 361

	/*
R
Robert Moore 已提交
362 363
	 * This is where we evaluate the address and length fields of the
	 * op_region declaration
L
Linus Torvalds 已提交
364
	 */
L
Len Brown 已提交
365
	node = op->common.node;
L
Linus Torvalds 已提交
366

367
	/* next_op points to the op that holds the space_ID */
L
Linus Torvalds 已提交
368 369 370 371 372 373 374 375 376

	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 已提交
377 378 379
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
380 381 382 383
	}

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

384 385 386
	status =
	    acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
				     walk_state);
L
Len Brown 已提交
387 388
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
389 390
	}

L
Len Brown 已提交
391
	obj_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
392
	if (!obj_desc) {
L
Len Brown 已提交
393
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
394 395 396 397 398 399 400 401 402
	}

	/*
	 * 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 已提交
403
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
404 405 406 407 408 409 410

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

R
Robert Moore 已提交
411
	obj_desc->region.address = (acpi_physical_address)
L
Len Brown 已提交
412 413
	    operand_desc->integer.value;
	acpi_ut_remove_reference(operand_desc);
L
Linus Torvalds 已提交
414

B
Bob Moore 已提交
415
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
L
Len Brown 已提交
416
			  obj_desc,
417
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
L
Len Brown 已提交
418
			  obj_desc->region.length));
L
Linus Torvalds 已提交
419 420 421 422

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

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;
L
Len Brown 已提交
423
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
424 425
}

426 427 428 429 430
/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_eval_table_region_operands
 *
 * PARAMETERS:  walk_state      - Current walk
431
 *              op              - A valid region Op object
432 433 434
 *
 * RETURN:      Status
 *
435 436 437
 * DESCRIPTION: Get region address and length.
 *              Called from acpi_ds_exec_end_op during data_table_region parse
 *              tree walk.
438 439 440 441 442 443 444 445 446 447 448 449 450
 *
 ******************************************************************************/

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;
	struct acpi_table_header *table;
451
	u32 table_index;
452 453 454 455

	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);

	/*
L
Lv Zheng 已提交
456 457
	 * This is where we evaluate the Signature string, oem_id string,
	 * and oem_table_id string of the Data Table Region declaration
458 459 460
	 */
	node = op->common.node;

L
Lv Zheng 已提交
461
	/* next_op points to Signature string op */
462 463 464 465

	next_op = op->common.value.arg;

	/*
L
Lv Zheng 已提交
466 467
	 * Evaluate/create the Signature string, oem_id string,
	 * and oem_table_id string operands
468 469 470 471 472 473
	 */
	status = acpi_ds_create_operands(walk_state, next_op);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

474 475
	operand = &walk_state->operands[0];

476
	/*
L
Lv Zheng 已提交
477 478
	 * Resolve the Signature string, oem_id string,
	 * and oem_table_id string operands
479
	 */
480 481 482
	status =
	    acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
				     walk_state);
483
	if (ACPI_FAILURE(status)) {
484
		goto cleanup;
485 486 487 488 489 490 491 492
	}

	/* 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)) {
493 494 495 496 497 498 499 500
		if (status == AE_NOT_FOUND) {
			ACPI_ERROR((AE_INFO,
				    "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT",
				    operand[0]->string.pointer,
				    operand[1]->string.pointer,
				    operand[2]->string.pointer));
		}
		goto cleanup;
501 502 503 504
	}

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
505
		goto cleanup;
506 507 508 509
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
510 511
		status = AE_NOT_EXIST;
		goto cleanup;
512 513
	}

514
	obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
515 516 517 518
	obj_desc->region.length = table->length;

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
519
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
520 521 522 523 524 525
			  obj_desc->region.length));

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

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

526 527 528 529 530
cleanup:
	acpi_ut_remove_reference(operand[0]);
	acpi_ut_remove_reference(operand[1]);
	acpi_ut_remove_reference(operand[2]);

531 532 533
	return_ACPI_STATUS(status);
}

R
Robert Moore 已提交
534
/*******************************************************************************
L
Linus Torvalds 已提交
535 536 537 538
 *
 * FUNCTION:    acpi_ds_eval_data_object_operands
 *
 * PARAMETERS:  walk_state      - Current walk
539
 *              op              - A valid data_object Op object
L
Linus Torvalds 已提交
540 541 542 543 544 545 546
 *              obj_desc        - data_object
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Get the operands and complete the following data object types:
 *              Buffer, Package.
 *
R
Robert Moore 已提交
547
 ******************************************************************************/
L
Linus Torvalds 已提交
548 549

acpi_status
L
Len Brown 已提交
550 551 552
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 已提交
553
{
L
Len Brown 已提交
554 555 556
	acpi_status status;
	union acpi_operand_object *arg_desc;
	u32 length;
L
Linus Torvalds 已提交
557

B
Bob Moore 已提交
558
	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
L
Linus Torvalds 已提交
559 560 561

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

562 563 564 565 566 567
	/*
	 * 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;

568 569 570 571
	/* Ignore if child is not valid */

	if (!op->common.value.arg) {
		ACPI_ERROR((AE_INFO,
572 573
			    "Missing child while evaluating opcode %4.4X, Op %p",
			    op->common.aml_opcode, op));
574 575 576
		return_ACPI_STATUS(AE_OK);
	}

L
Len Brown 已提交
577 578 579
	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
580 581
	}

L
Len Brown 已提交
582 583 584 585 586 587
	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 已提交
588 589 590 591
	}

	/* Extract length operand */

L
Len Brown 已提交
592
	arg_desc = walk_state->operands[walk_state->num_operands - 1];
L
Linus Torvalds 已提交
593 594 595 596
	length = (u32) arg_desc->integer.value;

	/* Cleanup for length operand */

L
Len Brown 已提交
597 598 599
	status = acpi_ds_obj_stack_pop(1, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
600 601
	}

L
Len Brown 已提交
602
	acpi_ut_remove_reference(arg_desc);
L
Linus Torvalds 已提交
603 604 605 606 607 608 609

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

L
Len Brown 已提交
610 611 612
		status =
		    acpi_ds_build_internal_buffer_obj(walk_state, op, length,
						      &obj_desc);
L
Linus Torvalds 已提交
613 614 615
		break;

	case AML_PACKAGE_OP:
616
	case AML_VARIABLE_PACKAGE_OP:
L
Linus Torvalds 已提交
617

L
Len Brown 已提交
618 619 620
		status =
		    acpi_ds_build_internal_package_obj(walk_state, op, length,
						       &obj_desc);
L
Linus Torvalds 已提交
621 622 623
		break;

	default:
624

L
Len Brown 已提交
625
		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
L
Linus Torvalds 已提交
626 627
	}

L
Len Brown 已提交
628
	if (ACPI_SUCCESS(status)) {
L
Linus Torvalds 已提交
629
		/*
R
Robert Moore 已提交
630
		 * Return the object in the walk_state, unless the parent is a package -
L
Linus Torvalds 已提交
631 632 633 634
		 * in this case, the return object will be stored in the parse tree
		 * for the package.
		 */
		if ((!op->common.parent) ||
L
Len Brown 已提交
635 636
		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
		     (op->common.parent->common.aml_opcode !=
637
		      AML_VARIABLE_PACKAGE_OP)
L
Lv Zheng 已提交
638 639
		     && (op->common.parent->common.aml_opcode !=
			 AML_NAME_OP))) {
L
Linus Torvalds 已提交
640 641 642 643
			walk_state->result_obj = obj_desc;
		}
	}

L
Len Brown 已提交
644
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
645 646
}

647 648 649 650 651
/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_eval_bank_field_operands
 *
 * PARAMETERS:  walk_state      - Current walk
652
 *              op              - A valid bank_field Op object
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
 *
 * 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);
	}

709 710
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
	/*
	 * 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);
}