xref: /OK3568_Linux_fs/kernel/drivers/acpi/acpica/exoparg2.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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