cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dsopcode.c (20126B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: dsopcode - Dispatcher support for regions and fields
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acparser.h"
     13#include "amlcode.h"
     14#include "acdispat.h"
     15#include "acinterp.h"
     16#include "acnamesp.h"
     17#include "acevents.h"
     18#include "actables.h"
     19
     20#define _COMPONENT          ACPI_DISPATCHER
     21ACPI_MODULE_NAME("dsopcode")
     22
     23/* Local prototypes */
     24static acpi_status
     25acpi_ds_init_buffer_field(u16 aml_opcode,
     26			  union acpi_operand_object *obj_desc,
     27			  union acpi_operand_object *buffer_desc,
     28			  union acpi_operand_object *offset_desc,
     29			  union acpi_operand_object *length_desc,
     30			  union acpi_operand_object *result_desc);
     31
     32/*******************************************************************************
     33 *
     34 * FUNCTION:    acpi_ds_initialize_region
     35 *
     36 * PARAMETERS:  obj_handle      - Region namespace node
     37 *
     38 * RETURN:      Status
     39 *
     40 * DESCRIPTION: Front end to ev_initialize_region
     41 *
     42 ******************************************************************************/
     43
     44acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)
     45{
     46	union acpi_operand_object *obj_desc;
     47	acpi_status status;
     48
     49	obj_desc = acpi_ns_get_attached_object(obj_handle);
     50
     51	/* Namespace is NOT locked */
     52
     53	status = acpi_ev_initialize_region(obj_desc);
     54	return (status);
     55}
     56
     57/*******************************************************************************
     58 *
     59 * FUNCTION:    acpi_ds_init_buffer_field
     60 *
     61 * PARAMETERS:  aml_opcode      - create_xxx_field
     62 *              obj_desc        - buffer_field object
     63 *              buffer_desc     - Host Buffer
     64 *              offset_desc     - Offset into buffer
     65 *              length_desc     - Length of field (CREATE_FIELD_OP only)
     66 *              result_desc     - Where to store the result
     67 *
     68 * RETURN:      Status
     69 *
     70 * DESCRIPTION: Perform actual initialization of a buffer field
     71 *
     72 ******************************************************************************/
     73
     74static acpi_status
     75acpi_ds_init_buffer_field(u16 aml_opcode,
     76			  union acpi_operand_object *obj_desc,
     77			  union acpi_operand_object *buffer_desc,
     78			  union acpi_operand_object *offset_desc,
     79			  union acpi_operand_object *length_desc,
     80			  union acpi_operand_object *result_desc)
     81{
     82	u32 offset;
     83	u32 bit_offset;
     84	u32 bit_count;
     85	u8 field_flags;
     86	acpi_status status;
     87
     88	ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);
     89
     90	/* Host object must be a Buffer */
     91
     92	if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {
     93		ACPI_ERROR((AE_INFO,
     94			    "Target of Create Field is not a Buffer object - %s",
     95			    acpi_ut_get_object_type_name(buffer_desc)));
     96
     97		status = AE_AML_OPERAND_TYPE;
     98		goto cleanup;
     99	}
    100
    101	/*
    102	 * The last parameter to all of these opcodes (result_desc) started
    103	 * out as a name_string, and should therefore now be a NS node
    104	 * after resolution in acpi_ex_resolve_operands().
    105	 */
    106	if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {
    107		ACPI_ERROR((AE_INFO,
    108			    "(%s) destination not a NS Node [%s]",
    109			    acpi_ps_get_opcode_name(aml_opcode),
    110			    acpi_ut_get_descriptor_name(result_desc)));
    111
    112		status = AE_AML_OPERAND_TYPE;
    113		goto cleanup;
    114	}
    115
    116	offset = (u32) offset_desc->integer.value;
    117
    118	/*
    119	 * Setup the Bit offsets and counts, according to the opcode
    120	 */
    121	switch (aml_opcode) {
    122	case AML_CREATE_FIELD_OP:
    123
    124		/* Offset is in bits, count is in bits */
    125
    126		field_flags = AML_FIELD_ACCESS_BYTE;
    127		bit_offset = offset;
    128		bit_count = (u32) length_desc->integer.value;
    129
    130		/* Must have a valid (>0) bit count */
    131
    132		if (bit_count == 0) {
    133			ACPI_BIOS_ERROR((AE_INFO,
    134					 "Attempt to CreateField of length zero"));
    135			status = AE_AML_OPERAND_VALUE;
    136			goto cleanup;
    137		}
    138		break;
    139
    140	case AML_CREATE_BIT_FIELD_OP:
    141
    142		/* Offset is in bits, Field is one bit */
    143
    144		bit_offset = offset;
    145		bit_count = 1;
    146		field_flags = AML_FIELD_ACCESS_BYTE;
    147		break;
    148
    149	case AML_CREATE_BYTE_FIELD_OP:
    150
    151		/* Offset is in bytes, field is one byte */
    152
    153		bit_offset = 8 * offset;
    154		bit_count = 8;
    155		field_flags = AML_FIELD_ACCESS_BYTE;
    156		break;
    157
    158	case AML_CREATE_WORD_FIELD_OP:
    159
    160		/* Offset is in bytes, field is one word */
    161
    162		bit_offset = 8 * offset;
    163		bit_count = 16;
    164		field_flags = AML_FIELD_ACCESS_WORD;
    165		break;
    166
    167	case AML_CREATE_DWORD_FIELD_OP:
    168
    169		/* Offset is in bytes, field is one dword */
    170
    171		bit_offset = 8 * offset;
    172		bit_count = 32;
    173		field_flags = AML_FIELD_ACCESS_DWORD;
    174		break;
    175
    176	case AML_CREATE_QWORD_FIELD_OP:
    177
    178		/* Offset is in bytes, field is one qword */
    179
    180		bit_offset = 8 * offset;
    181		bit_count = 64;
    182		field_flags = AML_FIELD_ACCESS_QWORD;
    183		break;
    184
    185	default:
    186
    187		ACPI_ERROR((AE_INFO,
    188			    "Unknown field creation opcode 0x%02X",
    189			    aml_opcode));
    190		status = AE_AML_BAD_OPCODE;
    191		goto cleanup;
    192	}
    193
    194	/* Entire field must fit within the current length of the buffer */
    195
    196	if ((bit_offset + bit_count) > (8 * (u32)buffer_desc->buffer.length)) {
    197		status = AE_AML_BUFFER_LIMIT;
    198		ACPI_BIOS_EXCEPTION((AE_INFO, status,
    199				     "Field [%4.4s] at bit offset/length %u/%u "
    200				     "exceeds size of target Buffer (%u bits)",
    201				     acpi_ut_get_node_name(result_desc),
    202				     bit_offset, bit_count,
    203				     8 * (u32)buffer_desc->buffer.length));
    204		goto cleanup;
    205	}
    206
    207	/*
    208	 * Initialize areas of the field object that are common to all fields
    209	 * For field_flags, use LOCK_RULE = 0 (NO_LOCK),
    210	 * UPDATE_RULE = 0 (UPDATE_PRESERVE)
    211	 */
    212	status =
    213	    acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
    214					     bit_offset, bit_count);
    215	if (ACPI_FAILURE(status)) {
    216		goto cleanup;
    217	}
    218
    219	obj_desc->buffer_field.buffer_obj = buffer_desc;
    220	obj_desc->buffer_field.is_create_field =
    221	    aml_opcode == AML_CREATE_FIELD_OP;
    222
    223	/* Reference count for buffer_desc inherits obj_desc count */
    224
    225	buffer_desc->common.reference_count = (u16)
    226	    (buffer_desc->common.reference_count +
    227	     obj_desc->common.reference_count);
    228
    229cleanup:
    230
    231	/* Always delete the operands */
    232
    233	acpi_ut_remove_reference(offset_desc);
    234	acpi_ut_remove_reference(buffer_desc);
    235
    236	if (aml_opcode == AML_CREATE_FIELD_OP) {
    237		acpi_ut_remove_reference(length_desc);
    238	}
    239
    240	/* On failure, delete the result descriptor */
    241
    242	if (ACPI_FAILURE(status)) {
    243		acpi_ut_remove_reference(result_desc);	/* Result descriptor */
    244	} else {
    245		/* Now the address and length are valid for this buffer_field */
    246
    247		obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
    248	}
    249
    250	return_ACPI_STATUS(status);
    251}
    252
    253/*******************************************************************************
    254 *
    255 * FUNCTION:    acpi_ds_eval_buffer_field_operands
    256 *
    257 * PARAMETERS:  walk_state      - Current walk
    258 *              op              - A valid buffer_field Op object
    259 *
    260 * RETURN:      Status
    261 *
    262 * DESCRIPTION: Get buffer_field Buffer and Index
    263 *              Called from acpi_ds_exec_end_op during buffer_field parse tree walk
    264 *
    265 ******************************************************************************/
    266
    267acpi_status
    268acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
    269				   union acpi_parse_object *op)
    270{
    271	acpi_status status;
    272	union acpi_operand_object *obj_desc;
    273	struct acpi_namespace_node *node;
    274	union acpi_parse_object *next_op;
    275
    276	ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);
    277
    278	/*
    279	 * This is where we evaluate the address and length fields of the
    280	 * create_xxx_field declaration
    281	 */
    282	node = op->common.node;
    283
    284	/* next_op points to the op that holds the Buffer */
    285
    286	next_op = op->common.value.arg;
    287
    288	/* Evaluate/create the address and length operands */
    289
    290	status = acpi_ds_create_operands(walk_state, next_op);
    291	if (ACPI_FAILURE(status)) {
    292		return_ACPI_STATUS(status);
    293	}
    294
    295	obj_desc = acpi_ns_get_attached_object(node);
    296	if (!obj_desc) {
    297		return_ACPI_STATUS(AE_NOT_EXIST);
    298	}
    299
    300	/* Resolve the operands */
    301
    302	status =
    303	    acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
    304				     walk_state);
    305	if (ACPI_FAILURE(status)) {
    306		ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
    307			    acpi_ps_get_opcode_name(op->common.aml_opcode),
    308			    status));
    309
    310		return_ACPI_STATUS(status);
    311	}
    312
    313	/* Initialize the Buffer Field */
    314
    315	if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
    316
    317		/* NOTE: Slightly different operands for this opcode */
    318
    319		status =
    320		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
    321					      walk_state->operands[0],
    322					      walk_state->operands[1],
    323					      walk_state->operands[2],
    324					      walk_state->operands[3]);
    325	} else {
    326		/* All other, create_xxx_field opcodes */
    327
    328		status =
    329		    acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,
    330					      walk_state->operands[0],
    331					      walk_state->operands[1], NULL,
    332					      walk_state->operands[2]);
    333	}
    334
    335	return_ACPI_STATUS(status);
    336}
    337
    338/*******************************************************************************
    339 *
    340 * FUNCTION:    acpi_ds_eval_region_operands
    341 *
    342 * PARAMETERS:  walk_state      - Current walk
    343 *              op              - A valid region Op object
    344 *
    345 * RETURN:      Status
    346 *
    347 * DESCRIPTION: Get region address and length
    348 *              Called from acpi_ds_exec_end_op during op_region parse tree walk
    349 *
    350 ******************************************************************************/
    351
    352acpi_status
    353acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,
    354			     union acpi_parse_object *op)
    355{
    356	acpi_status status;
    357	union acpi_operand_object *obj_desc;
    358	union acpi_operand_object *operand_desc;
    359	struct acpi_namespace_node *node;
    360	union acpi_parse_object *next_op;
    361	acpi_adr_space_type space_id;
    362
    363	ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);
    364
    365	/*
    366	 * This is where we evaluate the address and length fields of the
    367	 * op_region declaration
    368	 */
    369	node = op->common.node;
    370
    371	/* next_op points to the op that holds the space_ID */
    372
    373	next_op = op->common.value.arg;
    374	space_id = (acpi_adr_space_type)next_op->common.value.integer;
    375
    376	/* next_op points to address op */
    377
    378	next_op = next_op->common.next;
    379
    380	/* Evaluate/create the address and length operands */
    381
    382	status = acpi_ds_create_operands(walk_state, next_op);
    383	if (ACPI_FAILURE(status)) {
    384		return_ACPI_STATUS(status);
    385	}
    386
    387	/* Resolve the length and address operands to numbers */
    388
    389	status =
    390	    acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
    391				     walk_state);
    392	if (ACPI_FAILURE(status)) {
    393		return_ACPI_STATUS(status);
    394	}
    395
    396	obj_desc = acpi_ns_get_attached_object(node);
    397	if (!obj_desc) {
    398		return_ACPI_STATUS(AE_NOT_EXIST);
    399	}
    400
    401	/*
    402	 * Get the length operand and save it
    403	 * (at Top of stack)
    404	 */
    405	operand_desc = walk_state->operands[walk_state->num_operands - 1];
    406
    407	obj_desc->region.length = (u32) operand_desc->integer.value;
    408	acpi_ut_remove_reference(operand_desc);
    409
    410	/* A zero-length operation region is unusable. Just warn */
    411
    412	if (!obj_desc->region.length
    413	    && (space_id < ACPI_NUM_PREDEFINED_REGIONS)) {
    414		ACPI_WARNING((AE_INFO,
    415			      "Operation Region [%4.4s] has zero length (SpaceId %X)",
    416			      node->name.ascii, space_id));
    417	}
    418
    419	/*
    420	 * Get the address and save it
    421	 * (at top of stack - 1)
    422	 */
    423	operand_desc = walk_state->operands[walk_state->num_operands - 2];
    424
    425	obj_desc->region.address = (acpi_physical_address)
    426	    operand_desc->integer.value;
    427	acpi_ut_remove_reference(operand_desc);
    428
    429	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
    430			  obj_desc,
    431			  ACPI_FORMAT_UINT64(obj_desc->region.address),
    432			  obj_desc->region.length));
    433
    434	status = acpi_ut_add_address_range(obj_desc->region.space_id,
    435					   obj_desc->region.address,
    436					   obj_desc->region.length, node);
    437
    438	/* Now the address and length are valid for this opregion */
    439
    440	obj_desc->region.flags |= AOPOBJ_DATA_VALID;
    441	return_ACPI_STATUS(status);
    442}
    443
    444/*******************************************************************************
    445 *
    446 * FUNCTION:    acpi_ds_eval_table_region_operands
    447 *
    448 * PARAMETERS:  walk_state      - Current walk
    449 *              op              - A valid region Op object
    450 *
    451 * RETURN:      Status
    452 *
    453 * DESCRIPTION: Get region address and length.
    454 *              Called from acpi_ds_exec_end_op during data_table_region parse
    455 *              tree walk.
    456 *
    457 ******************************************************************************/
    458
    459acpi_status
    460acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,
    461				   union acpi_parse_object *op)
    462{
    463	acpi_status status;
    464	union acpi_operand_object *obj_desc;
    465	union acpi_operand_object **operand;
    466	struct acpi_namespace_node *node;
    467	union acpi_parse_object *next_op;
    468	struct acpi_table_header *table;
    469	u32 table_index;
    470
    471	ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);
    472
    473	/*
    474	 * This is where we evaluate the Signature string, oem_id string,
    475	 * and oem_table_id string of the Data Table Region declaration
    476	 */
    477	node = op->common.node;
    478
    479	/* next_op points to Signature string op */
    480
    481	next_op = op->common.value.arg;
    482
    483	/*
    484	 * Evaluate/create the Signature string, oem_id string,
    485	 * and oem_table_id string operands
    486	 */
    487	status = acpi_ds_create_operands(walk_state, next_op);
    488	if (ACPI_FAILURE(status)) {
    489		return_ACPI_STATUS(status);
    490	}
    491
    492	operand = &walk_state->operands[0];
    493
    494	/*
    495	 * Resolve the Signature string, oem_id string,
    496	 * and oem_table_id string operands
    497	 */
    498	status =
    499	    acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
    500				     walk_state);
    501	if (ACPI_FAILURE(status)) {
    502		goto cleanup;
    503	}
    504
    505	/* Find the ACPI table */
    506
    507	status = acpi_tb_find_table(operand[0]->string.pointer,
    508				    operand[1]->string.pointer,
    509				    operand[2]->string.pointer, &table_index);
    510	if (ACPI_FAILURE(status)) {
    511		if (status == AE_NOT_FOUND) {
    512			ACPI_ERROR((AE_INFO,
    513				    "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT",
    514				    operand[0]->string.pointer,
    515				    operand[1]->string.pointer,
    516				    operand[2]->string.pointer));
    517		}
    518		goto cleanup;
    519	}
    520
    521	status = acpi_get_table_by_index(table_index, &table);
    522	if (ACPI_FAILURE(status)) {
    523		goto cleanup;
    524	}
    525
    526	obj_desc = acpi_ns_get_attached_object(node);
    527	if (!obj_desc) {
    528		status = AE_NOT_EXIST;
    529		goto cleanup;
    530	}
    531
    532	obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table);
    533	obj_desc->region.length = table->length;
    534	obj_desc->region.pointer = table;
    535
    536	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",
    537			  obj_desc,
    538			  ACPI_FORMAT_UINT64(obj_desc->region.address),
    539			  obj_desc->region.length));
    540
    541	/* Now the address and length are valid for this opregion */
    542
    543	obj_desc->region.flags |= AOPOBJ_DATA_VALID;
    544
    545cleanup:
    546	acpi_ut_remove_reference(operand[0]);
    547	acpi_ut_remove_reference(operand[1]);
    548	acpi_ut_remove_reference(operand[2]);
    549
    550	return_ACPI_STATUS(status);
    551}
    552
    553/*******************************************************************************
    554 *
    555 * FUNCTION:    acpi_ds_eval_data_object_operands
    556 *
    557 * PARAMETERS:  walk_state      - Current walk
    558 *              op              - A valid data_object Op object
    559 *              obj_desc        - data_object
    560 *
    561 * RETURN:      Status
    562 *
    563 * DESCRIPTION: Get the operands and complete the following data object types:
    564 *              Buffer, Package.
    565 *
    566 ******************************************************************************/
    567
    568acpi_status
    569acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
    570				  union acpi_parse_object *op,
    571				  union acpi_operand_object *obj_desc)
    572{
    573	acpi_status status;
    574	union acpi_operand_object *arg_desc;
    575	u32 length;
    576
    577	ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);
    578
    579	/* The first operand (for all of these data objects) is the length */
    580
    581	/*
    582	 * Set proper index into operand stack for acpi_ds_obj_stack_push
    583	 * invoked inside acpi_ds_create_operand.
    584	 */
    585	walk_state->operand_index = walk_state->num_operands;
    586
    587	/* Ignore if child is not valid */
    588
    589	if (!op->common.value.arg) {
    590		ACPI_ERROR((AE_INFO,
    591			    "Missing child while evaluating opcode %4.4X, Op %p",
    592			    op->common.aml_opcode, op));
    593		return_ACPI_STATUS(AE_OK);
    594	}
    595
    596	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
    597	if (ACPI_FAILURE(status)) {
    598		return_ACPI_STATUS(status);
    599	}
    600
    601	status = acpi_ex_resolve_operands(walk_state->opcode,
    602					  &(walk_state->
    603					    operands[walk_state->num_operands -
    604						     1]), walk_state);
    605	if (ACPI_FAILURE(status)) {
    606		return_ACPI_STATUS(status);
    607	}
    608
    609	/* Extract length operand */
    610
    611	arg_desc = walk_state->operands[walk_state->num_operands - 1];
    612	length = (u32) arg_desc->integer.value;
    613
    614	/* Cleanup for length operand */
    615
    616	status = acpi_ds_obj_stack_pop(1, walk_state);
    617	if (ACPI_FAILURE(status)) {
    618		return_ACPI_STATUS(status);
    619	}
    620
    621	acpi_ut_remove_reference(arg_desc);
    622
    623	/*
    624	 * Create the actual data object
    625	 */
    626	switch (op->common.aml_opcode) {
    627	case AML_BUFFER_OP:
    628
    629		status =
    630		    acpi_ds_build_internal_buffer_obj(walk_state, op, length,
    631						      &obj_desc);
    632		break;
    633
    634	case AML_PACKAGE_OP:
    635	case AML_VARIABLE_PACKAGE_OP:
    636
    637		status =
    638		    acpi_ds_build_internal_package_obj(walk_state, op, length,
    639						       &obj_desc);
    640		break;
    641
    642	default:
    643
    644		return_ACPI_STATUS(AE_AML_BAD_OPCODE);
    645	}
    646
    647	if (ACPI_SUCCESS(status)) {
    648		/*
    649		 * Return the object in the walk_state, unless the parent is a package -
    650		 * in this case, the return object will be stored in the parse tree
    651		 * for the package.
    652		 */
    653		if ((!op->common.parent) ||
    654		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
    655		     (op->common.parent->common.aml_opcode !=
    656		      AML_VARIABLE_PACKAGE_OP)
    657		     && (op->common.parent->common.aml_opcode !=
    658			 AML_NAME_OP))) {
    659			walk_state->result_obj = obj_desc;
    660		}
    661	}
    662
    663	return_ACPI_STATUS(status);
    664}
    665
    666/*******************************************************************************
    667 *
    668 * FUNCTION:    acpi_ds_eval_bank_field_operands
    669 *
    670 * PARAMETERS:  walk_state      - Current walk
    671 *              op              - A valid bank_field Op object
    672 *
    673 * RETURN:      Status
    674 *
    675 * DESCRIPTION: Get bank_field bank_value
    676 *              Called from acpi_ds_exec_end_op during bank_field parse tree walk
    677 *
    678 ******************************************************************************/
    679
    680acpi_status
    681acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,
    682				 union acpi_parse_object *op)
    683{
    684	acpi_status status;
    685	union acpi_operand_object *obj_desc;
    686	union acpi_operand_object *operand_desc;
    687	struct acpi_namespace_node *node;
    688	union acpi_parse_object *next_op;
    689	union acpi_parse_object *arg;
    690
    691	ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);
    692
    693	/*
    694	 * This is where we evaluate the bank_value field of the
    695	 * bank_field declaration
    696	 */
    697
    698	/* next_op points to the op that holds the Region */
    699
    700	next_op = op->common.value.arg;
    701
    702	/* next_op points to the op that holds the Bank Register */
    703
    704	next_op = next_op->common.next;
    705
    706	/* next_op points to the op that holds the Bank Value */
    707
    708	next_op = next_op->common.next;
    709
    710	/*
    711	 * Set proper index into operand stack for acpi_ds_obj_stack_push
    712	 * invoked inside acpi_ds_create_operand.
    713	 *
    714	 * We use walk_state->Operands[0] to store the evaluated bank_value
    715	 */
    716	walk_state->operand_index = 0;
    717
    718	status = acpi_ds_create_operand(walk_state, next_op, 0);
    719	if (ACPI_FAILURE(status)) {
    720		return_ACPI_STATUS(status);
    721	}
    722
    723	status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);
    724	if (ACPI_FAILURE(status)) {
    725		return_ACPI_STATUS(status);
    726	}
    727
    728	ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,
    729			   acpi_ps_get_opcode_name(op->common.aml_opcode), 1);
    730	/*
    731	 * Get the bank_value operand and save it
    732	 * (at Top of stack)
    733	 */
    734	operand_desc = walk_state->operands[0];
    735
    736	/* Arg points to the start Bank Field */
    737
    738	arg = acpi_ps_get_arg(op, 4);
    739	while (arg) {
    740
    741		/* Ignore OFFSET and ACCESSAS terms here */
    742
    743		if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
    744			node = arg->common.node;
    745
    746			obj_desc = acpi_ns_get_attached_object(node);
    747			if (!obj_desc) {
    748				return_ACPI_STATUS(AE_NOT_EXIST);
    749			}
    750
    751			obj_desc->bank_field.value =
    752			    (u32) operand_desc->integer.value;
    753		}
    754
    755		/* Move to next field in the list */
    756
    757		arg = arg->common.next;
    758	}
    759
    760	acpi_ut_remove_reference(operand_desc);
    761	return_ACPI_STATUS(status);
    762}