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