dsopcode.c 19.1 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 423
	status = acpi_ut_add_address_range(obj_desc->region.space_id,
					   obj_desc->region.address,
					   obj_desc->region.length, node);

L
Linus Torvalds 已提交
424 425 426
	/* Now the address and length are valid for this opregion */

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;
L
Len Brown 已提交
427
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
428 429
}

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

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;
455
	u32 table_index;
456 457 458 459

	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);

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

L
Lv Zheng 已提交
465
	/* next_op points to Signature string op */
466 467 468 469

	next_op = op->common.value.arg;

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

478 479
	operand = &walk_state->operands[0];

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

	/* 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)) {
497 498 499 500 501 502 503 504
		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;
505 506 507 508
	}

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
509
		goto cleanup;
510 511 512 513
	}

	obj_desc = acpi_ns_get_attached_object(node);
	if (!obj_desc) {
514 515
		status = AE_NOT_EXIST;
		goto cleanup;
516 517
	}

518
	obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
519 520 521 522
	obj_desc->region.length = table->length;

	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
			  obj_desc,
523
			  ACPI_FORMAT_UINT64(obj_desc->region.address),
524 525 526 527 528 529
			  obj_desc->region.length));

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

	obj_desc->region.flags |= AOPOBJ_DATA_VALID;

530 531 532 533 534
cleanup:
	acpi_ut_remove_reference(operand[0]);
	acpi_ut_remove_reference(operand[1]);
	acpi_ut_remove_reference(operand[2]);

535 536 537
	return_ACPI_STATUS(status);
}

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

acpi_status
L
Len Brown 已提交
554 555 556
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 已提交
557
{
L
Len Brown 已提交
558 559 560
	acpi_status status;
	union acpi_operand_object *arg_desc;
	u32 length;
L
Linus Torvalds 已提交
561

B
Bob Moore 已提交
562
	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
L
Linus Torvalds 已提交
563 564 565

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

566 567 568 569 570 571
	/*
	 * 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;

572 573 574 575
	/* Ignore if child is not valid */

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

L
Len Brown 已提交
581 582 583
	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
584 585
	}

L
Len Brown 已提交
586 587 588 589 590 591
	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 已提交
592 593 594 595
	}

	/* Extract length operand */

L
Len Brown 已提交
596
	arg_desc = walk_state->operands[walk_state->num_operands - 1];
L
Linus Torvalds 已提交
597 598 599 600
	length = (u32) arg_desc->integer.value;

	/* Cleanup for length operand */

L
Len Brown 已提交
601 602 603
	status = acpi_ds_obj_stack_pop(1, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
604 605
	}

L
Len Brown 已提交
606
	acpi_ut_remove_reference(arg_desc);
L
Linus Torvalds 已提交
607 608 609 610 611 612 613

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

L
Len Brown 已提交
614 615 616
		status =
		    acpi_ds_build_internal_buffer_obj(walk_state, op, length,
						      &obj_desc);
L
Linus Torvalds 已提交
617 618 619
		break;

	case AML_PACKAGE_OP:
620
	case AML_VARIABLE_PACKAGE_OP:
L
Linus Torvalds 已提交
621

L
Len Brown 已提交
622 623 624
		status =
		    acpi_ds_build_internal_package_obj(walk_state, op, length,
						       &obj_desc);
L
Linus Torvalds 已提交
625 626 627
		break;

	default:
628

L
Len Brown 已提交
629
		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
L
Linus Torvalds 已提交
630 631
	}

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

L
Len Brown 已提交
648
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
649 650
}

651 652 653 654 655
/*******************************************************************************
 *
 * FUNCTION:    acpi_ds_eval_bank_field_operands
 *
 * PARAMETERS:  walk_state      - Current walk
656
 *              op              - A valid bank_field Op object
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 709 710 711 712
 *
 * 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);
	}

713 714
	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
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 744 745 746 747
	/*
	 * 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);
}