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