1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
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 "acinterp.h"
14*4882a593Smuzhiyun #include "acevents.h"
15*4882a593Smuzhiyun #include "amlcode.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define _COMPONENT ACPI_EXECUTER
18*4882a593Smuzhiyun ACPI_MODULE_NAME("exoparg2")
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /*!
21*4882a593Smuzhiyun * Naming convention for AML interpreter execution routines.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * The routines that begin execution of AML opcodes are named with a common
24*4882a593Smuzhiyun * convention based upon the number of arguments, the number of target operands,
25*4882a593Smuzhiyun * and whether or not a value is returned:
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * AcpiExOpcode_xA_yT_zR
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * Where:
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * xA - ARGUMENTS: The number of arguments (input operands) that are
32*4882a593Smuzhiyun * required for this opcode type (1 through 6 args).
33*4882a593Smuzhiyun * yT - TARGETS: The number of targets (output operands) that are required
34*4882a593Smuzhiyun * for this opcode type (0, 1, or 2 targets).
35*4882a593Smuzhiyun * zR - RETURN VALUE: Indicates whether this opcode type returns a value
36*4882a593Smuzhiyun * as the function return (0 or 1).
37*4882a593Smuzhiyun *
38*4882a593Smuzhiyun * The AcpiExOpcode* functions are called via the Dispatcher component with
39*4882a593Smuzhiyun * fully resolved operands.
40*4882a593Smuzhiyun !*/
41*4882a593Smuzhiyun /*******************************************************************************
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun * FUNCTION: acpi_ex_opcode_2A_0T_0R
44*4882a593Smuzhiyun *
45*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk state
46*4882a593Smuzhiyun *
47*4882a593Smuzhiyun * RETURN: Status
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * DESCRIPTION: Execute opcode with two arguments, no target, and no return
50*4882a593Smuzhiyun * value.
51*4882a593Smuzhiyun *
52*4882a593Smuzhiyun * ALLOCATION: Deletes both operands
53*4882a593Smuzhiyun *
54*4882a593Smuzhiyun ******************************************************************************/
acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state * walk_state)55*4882a593Smuzhiyun acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun union acpi_operand_object **operand = &walk_state->operands[0];
58*4882a593Smuzhiyun struct acpi_namespace_node *node;
59*4882a593Smuzhiyun u32 value;
60*4882a593Smuzhiyun acpi_status status = AE_OK;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_0R,
63*4882a593Smuzhiyun acpi_ps_get_opcode_name(walk_state->opcode));
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun /* Examine the opcode */
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun switch (walk_state->opcode) {
68*4882a593Smuzhiyun case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* The first operand is a namespace node */
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun node = (struct acpi_namespace_node *)operand[0];
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* Second value is the notify value */
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun value = (u32) operand[1]->integer.value;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun /* Are notifies allowed on this object? */
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (!acpi_ev_is_notify_object(node)) {
81*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
82*4882a593Smuzhiyun "Unexpected notify object type [%s]",
83*4882a593Smuzhiyun acpi_ut_get_type_name(node->type)));
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun status = AE_AML_OPERAND_TYPE;
86*4882a593Smuzhiyun break;
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /*
90*4882a593Smuzhiyun * Dispatch the notify to the appropriate handler
91*4882a593Smuzhiyun * NOTE: the request is queued for execution after this method
92*4882a593Smuzhiyun * completes. The notify handlers are NOT invoked synchronously
93*4882a593Smuzhiyun * from this thread -- because handlers may in turn run other
94*4882a593Smuzhiyun * control methods.
95*4882a593Smuzhiyun */
96*4882a593Smuzhiyun status = acpi_ev_queue_notify_request(node, value);
97*4882a593Smuzhiyun break;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun default:
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
102*4882a593Smuzhiyun walk_state->opcode));
103*4882a593Smuzhiyun status = AE_AML_BAD_OPCODE;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun return_ACPI_STATUS(status);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /*******************************************************************************
110*4882a593Smuzhiyun *
111*4882a593Smuzhiyun * FUNCTION: acpi_ex_opcode_2A_2T_1R
112*4882a593Smuzhiyun *
113*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk state
114*4882a593Smuzhiyun *
115*4882a593Smuzhiyun * RETURN: Status
116*4882a593Smuzhiyun *
117*4882a593Smuzhiyun * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
118*4882a593Smuzhiyun * and one implicit return value.
119*4882a593Smuzhiyun *
120*4882a593Smuzhiyun ******************************************************************************/
121*4882a593Smuzhiyun
acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state * walk_state)122*4882a593Smuzhiyun acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun union acpi_operand_object **operand = &walk_state->operands[0];
125*4882a593Smuzhiyun union acpi_operand_object *return_desc1 = NULL;
126*4882a593Smuzhiyun union acpi_operand_object *return_desc2 = NULL;
127*4882a593Smuzhiyun acpi_status status;
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_2T_1R,
130*4882a593Smuzhiyun acpi_ps_get_opcode_name(walk_state->opcode));
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun /* Execute the opcode */
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun switch (walk_state->opcode) {
135*4882a593Smuzhiyun case AML_DIVIDE_OP:
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /* Divide (Dividend, Divisor, remainder_result quotient_result) */
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun return_desc1 =
140*4882a593Smuzhiyun acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
141*4882a593Smuzhiyun if (!return_desc1) {
142*4882a593Smuzhiyun status = AE_NO_MEMORY;
143*4882a593Smuzhiyun goto cleanup;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun return_desc2 =
147*4882a593Smuzhiyun acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
148*4882a593Smuzhiyun if (!return_desc2) {
149*4882a593Smuzhiyun status = AE_NO_MEMORY;
150*4882a593Smuzhiyun goto cleanup;
151*4882a593Smuzhiyun }
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Quotient to return_desc1, remainder to return_desc2 */
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun status = acpi_ut_divide(operand[0]->integer.value,
156*4882a593Smuzhiyun operand[1]->integer.value,
157*4882a593Smuzhiyun &return_desc1->integer.value,
158*4882a593Smuzhiyun &return_desc2->integer.value);
159*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
160*4882a593Smuzhiyun goto cleanup;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun break;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun default:
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
167*4882a593Smuzhiyun walk_state->opcode));
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun status = AE_AML_BAD_OPCODE;
170*4882a593Smuzhiyun goto cleanup;
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* Store the results to the target reference operands */
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun status = acpi_ex_store(return_desc2, operand[2], walk_state);
176*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
177*4882a593Smuzhiyun goto cleanup;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
180*4882a593Smuzhiyun status = acpi_ex_store(return_desc1, operand[3], walk_state);
181*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
182*4882a593Smuzhiyun goto cleanup;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun cleanup:
186*4882a593Smuzhiyun /*
187*4882a593Smuzhiyun * Since the remainder is not returned indirectly, remove a reference to
188*4882a593Smuzhiyun * it. Only the quotient is returned indirectly.
189*4882a593Smuzhiyun */
190*4882a593Smuzhiyun acpi_ut_remove_reference(return_desc2);
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /* Delete the return object */
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun acpi_ut_remove_reference(return_desc1);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun /* Save return object (the remainder) on success */
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun else {
202*4882a593Smuzhiyun walk_state->result_obj = return_desc1;
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun return_ACPI_STATUS(status);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun /*******************************************************************************
209*4882a593Smuzhiyun *
210*4882a593Smuzhiyun * FUNCTION: acpi_ex_opcode_2A_1T_1R
211*4882a593Smuzhiyun *
212*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk state
213*4882a593Smuzhiyun *
214*4882a593Smuzhiyun * RETURN: Status
215*4882a593Smuzhiyun *
216*4882a593Smuzhiyun * DESCRIPTION: Execute opcode with two arguments, one target, and a return
217*4882a593Smuzhiyun * value.
218*4882a593Smuzhiyun *
219*4882a593Smuzhiyun ******************************************************************************/
220*4882a593Smuzhiyun
acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state * walk_state)221*4882a593Smuzhiyun acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun union acpi_operand_object **operand = &walk_state->operands[0];
224*4882a593Smuzhiyun union acpi_operand_object *return_desc = NULL;
225*4882a593Smuzhiyun u64 index;
226*4882a593Smuzhiyun acpi_status status = AE_OK;
227*4882a593Smuzhiyun acpi_size length = 0;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_1T_1R,
230*4882a593Smuzhiyun acpi_ps_get_opcode_name(walk_state->opcode));
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun /* Execute the opcode */
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun if (walk_state->op_info->flags & AML_MATH) {
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun /* All simple math opcodes (add, etc.) */
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
239*4882a593Smuzhiyun if (!return_desc) {
240*4882a593Smuzhiyun status = AE_NO_MEMORY;
241*4882a593Smuzhiyun goto cleanup;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun return_desc->integer.value =
245*4882a593Smuzhiyun acpi_ex_do_math_op(walk_state->opcode,
246*4882a593Smuzhiyun operand[0]->integer.value,
247*4882a593Smuzhiyun operand[1]->integer.value);
248*4882a593Smuzhiyun goto store_result_to_target;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun switch (walk_state->opcode) {
252*4882a593Smuzhiyun case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
255*4882a593Smuzhiyun if (!return_desc) {
256*4882a593Smuzhiyun status = AE_NO_MEMORY;
257*4882a593Smuzhiyun goto cleanup;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun /* return_desc will contain the remainder */
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun status = acpi_ut_divide(operand[0]->integer.value,
263*4882a593Smuzhiyun operand[1]->integer.value,
264*4882a593Smuzhiyun NULL, &return_desc->integer.value);
265*4882a593Smuzhiyun break;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun case AML_CONCATENATE_OP: /* Concatenate (Data1, Data2, Result) */
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun status =
270*4882a593Smuzhiyun acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
271*4882a593Smuzhiyun walk_state);
272*4882a593Smuzhiyun break;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
275*4882a593Smuzhiyun /*
276*4882a593Smuzhiyun * Input object is guaranteed to be a buffer at this point (it may have
277*4882a593Smuzhiyun * been converted.) Copy the raw buffer data to a new object of
278*4882a593Smuzhiyun * type String.
279*4882a593Smuzhiyun */
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun /*
282*4882a593Smuzhiyun * Get the length of the new string. It is the smallest of:
283*4882a593Smuzhiyun * 1) Length of the input buffer
284*4882a593Smuzhiyun * 2) Max length as specified in the to_string operator
285*4882a593Smuzhiyun * 3) Length of input buffer up to a zero byte (null terminator)
286*4882a593Smuzhiyun *
287*4882a593Smuzhiyun * NOTE: A length of zero is ok, and will create a zero-length, null
288*4882a593Smuzhiyun * terminated string.
289*4882a593Smuzhiyun */
290*4882a593Smuzhiyun while ((length < operand[0]->buffer.length) && /* Length of input buffer */
291*4882a593Smuzhiyun (length < operand[1]->integer.value) && /* Length operand */
292*4882a593Smuzhiyun (operand[0]->buffer.pointer[length])) { /* Null terminator */
293*4882a593Smuzhiyun length++;
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun /* Allocate a new string object */
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun return_desc = acpi_ut_create_string_object(length);
299*4882a593Smuzhiyun if (!return_desc) {
300*4882a593Smuzhiyun status = AE_NO_MEMORY;
301*4882a593Smuzhiyun goto cleanup;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /*
305*4882a593Smuzhiyun * Copy the raw buffer data with no transform.
306*4882a593Smuzhiyun * (NULL terminated already)
307*4882a593Smuzhiyun */
308*4882a593Smuzhiyun memcpy(return_desc->string.pointer,
309*4882a593Smuzhiyun operand[0]->buffer.pointer, length);
310*4882a593Smuzhiyun break;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun case AML_CONCATENATE_TEMPLATE_OP:
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun status =
317*4882a593Smuzhiyun acpi_ex_concat_template(operand[0], operand[1],
318*4882a593Smuzhiyun &return_desc, walk_state);
319*4882a593Smuzhiyun break;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun case AML_INDEX_OP: /* Index (Source Index Result) */
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun /* Create the internal return object */
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun return_desc =
326*4882a593Smuzhiyun acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
327*4882a593Smuzhiyun if (!return_desc) {
328*4882a593Smuzhiyun status = AE_NO_MEMORY;
329*4882a593Smuzhiyun goto cleanup;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun /* Initialize the Index reference object */
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun index = operand[1]->integer.value;
335*4882a593Smuzhiyun return_desc->reference.value = (u32) index;
336*4882a593Smuzhiyun return_desc->reference.class = ACPI_REFCLASS_INDEX;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun /*
339*4882a593Smuzhiyun * At this point, the Source operand is a String, Buffer, or Package.
340*4882a593Smuzhiyun * Verify that the index is within range.
341*4882a593Smuzhiyun */
342*4882a593Smuzhiyun switch ((operand[0])->common.type) {
343*4882a593Smuzhiyun case ACPI_TYPE_STRING:
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun if (index >= operand[0]->string.length) {
346*4882a593Smuzhiyun length = operand[0]->string.length;
347*4882a593Smuzhiyun status = AE_AML_STRING_LIMIT;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun return_desc->reference.target_type =
351*4882a593Smuzhiyun ACPI_TYPE_BUFFER_FIELD;
352*4882a593Smuzhiyun return_desc->reference.index_pointer =
353*4882a593Smuzhiyun &(operand[0]->buffer.pointer[index]);
354*4882a593Smuzhiyun break;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun case ACPI_TYPE_BUFFER:
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun if (index >= operand[0]->buffer.length) {
359*4882a593Smuzhiyun length = operand[0]->buffer.length;
360*4882a593Smuzhiyun status = AE_AML_BUFFER_LIMIT;
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun
363*4882a593Smuzhiyun return_desc->reference.target_type =
364*4882a593Smuzhiyun ACPI_TYPE_BUFFER_FIELD;
365*4882a593Smuzhiyun return_desc->reference.index_pointer =
366*4882a593Smuzhiyun &(operand[0]->buffer.pointer[index]);
367*4882a593Smuzhiyun break;
368*4882a593Smuzhiyun
369*4882a593Smuzhiyun case ACPI_TYPE_PACKAGE:
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun if (index >= operand[0]->package.count) {
372*4882a593Smuzhiyun length = operand[0]->package.count;
373*4882a593Smuzhiyun status = AE_AML_PACKAGE_LIMIT;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
377*4882a593Smuzhiyun return_desc->reference.where =
378*4882a593Smuzhiyun &operand[0]->package.elements[index];
379*4882a593Smuzhiyun break;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun default:
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
384*4882a593Smuzhiyun "Invalid object type: %X",
385*4882a593Smuzhiyun (operand[0])->common.type));
386*4882a593Smuzhiyun status = AE_AML_INTERNAL;
387*4882a593Smuzhiyun goto cleanup;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun /* Failure means that the Index was beyond the end of the object */
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
393*4882a593Smuzhiyun ACPI_BIOS_EXCEPTION((AE_INFO, status,
394*4882a593Smuzhiyun "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
395*4882a593Smuzhiyun ACPI_FORMAT_UINT64(index),
396*4882a593Smuzhiyun (u32)length));
397*4882a593Smuzhiyun goto cleanup;
398*4882a593Smuzhiyun }
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun /*
401*4882a593Smuzhiyun * Save the target object and add a reference to it for the life
402*4882a593Smuzhiyun * of the index
403*4882a593Smuzhiyun */
404*4882a593Smuzhiyun return_desc->reference.object = operand[0];
405*4882a593Smuzhiyun acpi_ut_add_reference(operand[0]);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun /* Store the reference to the Target */
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun status = acpi_ex_store(return_desc, operand[2], walk_state);
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun /* Return the reference */
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun walk_state->result_obj = return_desc;
414*4882a593Smuzhiyun goto cleanup;
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun default:
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
419*4882a593Smuzhiyun walk_state->opcode));
420*4882a593Smuzhiyun status = AE_AML_BAD_OPCODE;
421*4882a593Smuzhiyun break;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun store_result_to_target:
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
427*4882a593Smuzhiyun /*
428*4882a593Smuzhiyun * Store the result of the operation (which is now in return_desc) into
429*4882a593Smuzhiyun * the Target descriptor.
430*4882a593Smuzhiyun */
431*4882a593Smuzhiyun status = acpi_ex_store(return_desc, operand[2], walk_state);
432*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
433*4882a593Smuzhiyun goto cleanup;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun if (!walk_state->result_obj) {
437*4882a593Smuzhiyun walk_state->result_obj = return_desc;
438*4882a593Smuzhiyun }
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun cleanup:
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun /* Delete return object on error */
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
446*4882a593Smuzhiyun acpi_ut_remove_reference(return_desc);
447*4882a593Smuzhiyun walk_state->result_obj = NULL;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun return_ACPI_STATUS(status);
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun /*******************************************************************************
454*4882a593Smuzhiyun *
455*4882a593Smuzhiyun * FUNCTION: acpi_ex_opcode_2A_0T_1R
456*4882a593Smuzhiyun *
457*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk state
458*4882a593Smuzhiyun *
459*4882a593Smuzhiyun * RETURN: Status
460*4882a593Smuzhiyun *
461*4882a593Smuzhiyun * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
462*4882a593Smuzhiyun *
463*4882a593Smuzhiyun ******************************************************************************/
464*4882a593Smuzhiyun
acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state * walk_state)465*4882a593Smuzhiyun acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state)
466*4882a593Smuzhiyun {
467*4882a593Smuzhiyun union acpi_operand_object **operand = &walk_state->operands[0];
468*4882a593Smuzhiyun union acpi_operand_object *return_desc = NULL;
469*4882a593Smuzhiyun acpi_status status = AE_OK;
470*4882a593Smuzhiyun u8 logical_result = FALSE;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun ACPI_FUNCTION_TRACE_STR(ex_opcode_2A_0T_1R,
473*4882a593Smuzhiyun acpi_ps_get_opcode_name(walk_state->opcode));
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun /* Create the internal return object */
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
478*4882a593Smuzhiyun if (!return_desc) {
479*4882a593Smuzhiyun status = AE_NO_MEMORY;
480*4882a593Smuzhiyun goto cleanup;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun /* Execute the Opcode */
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun /* logical_op (Operand0, Operand1) */
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun status = acpi_ex_do_logical_numeric_op(walk_state->opcode,
490*4882a593Smuzhiyun operand[0]->integer.
491*4882a593Smuzhiyun value,
492*4882a593Smuzhiyun operand[1]->integer.
493*4882a593Smuzhiyun value, &logical_result);
494*4882a593Smuzhiyun goto store_logical_result;
495*4882a593Smuzhiyun } else if (walk_state->op_info->flags & AML_LOGICAL) {
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /* logical_op (Operand0, Operand1) */
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun status = acpi_ex_do_logical_op(walk_state->opcode, operand[0],
500*4882a593Smuzhiyun operand[1], &logical_result);
501*4882a593Smuzhiyun goto store_logical_result;
502*4882a593Smuzhiyun }
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun switch (walk_state->opcode) {
505*4882a593Smuzhiyun case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun status =
508*4882a593Smuzhiyun acpi_ex_acquire_mutex(operand[1], operand[0], walk_state);
509*4882a593Smuzhiyun if (status == AE_TIME) {
510*4882a593Smuzhiyun logical_result = TRUE; /* TRUE = Acquire timed out */
511*4882a593Smuzhiyun status = AE_OK;
512*4882a593Smuzhiyun }
513*4882a593Smuzhiyun break;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun case AML_WAIT_OP: /* Wait (event_object, Timeout) */
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun status = acpi_ex_system_wait_event(operand[1], operand[0]);
518*4882a593Smuzhiyun if (status == AE_TIME) {
519*4882a593Smuzhiyun logical_result = TRUE; /* TRUE, Wait timed out */
520*4882a593Smuzhiyun status = AE_OK;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun break;
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun default:
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
527*4882a593Smuzhiyun walk_state->opcode));
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun status = AE_AML_BAD_OPCODE;
530*4882a593Smuzhiyun goto cleanup;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun store_logical_result:
534*4882a593Smuzhiyun /*
535*4882a593Smuzhiyun * Set return value to according to logical_result. logical TRUE (all ones)
536*4882a593Smuzhiyun * Default is FALSE (zero)
537*4882a593Smuzhiyun */
538*4882a593Smuzhiyun if (logical_result) {
539*4882a593Smuzhiyun return_desc->integer.value = ACPI_UINT64_MAX;
540*4882a593Smuzhiyun }
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun cleanup:
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun /* Delete return object on error */
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
547*4882a593Smuzhiyun acpi_ut_remove_reference(return_desc);
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /* Save return object on success */
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun else {
553*4882a593Smuzhiyun walk_state->result_obj = return_desc;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun return_ACPI_STATUS(status);
557*4882a593Smuzhiyun }
558