Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: exoparg1 - AML execution - opcodes with 1 argument
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 "acdispat.h"
14 : : #include "acinterp.h"
15 : : #include "amlcode.h"
16 : : #include "acnamesp.h"
17 : :
18 : : #define _COMPONENT ACPI_EXECUTER
19 : : ACPI_MODULE_NAME("exoparg1")
20 : :
21 : : /*!
22 : : * Naming convention for AML interpreter execution routines.
23 : : *
24 : : * The routines that begin execution of AML opcodes are named with a common
25 : : * convention based upon the number of arguments, the number of target operands,
26 : : * and whether or not a value is returned:
27 : : *
28 : : * AcpiExOpcode_xA_yT_zR
29 : : *
30 : : * Where:
31 : : *
32 : : * xA - ARGUMENTS: The number of arguments (input operands) that are
33 : : * required for this opcode type (0 through 6 args).
34 : : * yT - TARGETS: The number of targets (output operands) that are required
35 : : * for this opcode type (0, 1, or 2 targets).
36 : : * zR - RETURN VALUE: Indicates whether this opcode type returns a value
37 : : * as the function return (0 or 1).
38 : : *
39 : : * The AcpiExOpcode* functions are called via the Dispatcher component with
40 : : * fully resolved operands.
41 : : !*/
42 : : /*******************************************************************************
43 : : *
44 : : * FUNCTION: acpi_ex_opcode_0A_0T_1R
45 : : *
46 : : * PARAMETERS: walk_state - Current state (contains AML opcode)
47 : : *
48 : : * RETURN: Status
49 : : *
50 : : * DESCRIPTION: Execute operator with no operands, one return value
51 : : *
52 : : ******************************************************************************/
53 : 0 : acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
54 : : {
55 : 0 : acpi_status status = AE_OK;
56 : 0 : union acpi_operand_object *return_desc = NULL;
57 : :
58 : : ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R,
59 : 0 : acpi_ps_get_opcode_name(walk_state->opcode));
60 : :
61 : : /* Examine the AML opcode */
62 : :
63 [ # # ]: 0 : switch (walk_state->opcode) {
64 : 0 : case AML_TIMER_OP: /* Timer () */
65 : :
66 : : /* Create a return object of type Integer */
67 : :
68 : 0 : return_desc =
69 : 0 : acpi_ut_create_integer_object(acpi_os_get_timer());
70 [ # # ]: 0 : if (!return_desc) {
71 : 0 : status = AE_NO_MEMORY;
72 : 0 : goto cleanup;
73 : : }
74 : : break;
75 : :
76 : 0 : default: /* Unknown opcode */
77 : :
78 : 0 : ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
79 : : walk_state->opcode));
80 : 0 : status = AE_AML_BAD_OPCODE;
81 : 0 : break;
82 : : }
83 : :
84 : : cleanup:
85 : :
86 : : /* Delete return object on error */
87 : :
88 [ # # ]: 0 : if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
89 : 0 : acpi_ut_remove_reference(return_desc);
90 : 0 : walk_state->result_obj = NULL;
91 : : } else {
92 : : /* Save the return value */
93 : :
94 : 0 : walk_state->result_obj = return_desc;
95 : : }
96 : :
97 : 0 : return_ACPI_STATUS(status);
98 : : }
99 : :
100 : : /*******************************************************************************
101 : : *
102 : : * FUNCTION: acpi_ex_opcode_1A_0T_0R
103 : : *
104 : : * PARAMETERS: walk_state - Current state (contains AML opcode)
105 : : *
106 : : * RETURN: Status
107 : : *
108 : : * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
109 : : * object stack
110 : : *
111 : : ******************************************************************************/
112 : :
113 : 22 : acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)
114 : : {
115 : 22 : union acpi_operand_object **operand = &walk_state->operands[0];
116 : 22 : acpi_status status = AE_OK;
117 : :
118 : : ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R,
119 : 22 : acpi_ps_get_opcode_name(walk_state->opcode));
120 : :
121 : : /* Examine the AML opcode */
122 : :
123 [ + - - - : 22 : switch (walk_state->opcode) {
- - - ]
124 : 22 : case AML_RELEASE_OP: /* Release (mutex_object) */
125 : :
126 : 22 : status = acpi_ex_release_mutex(operand[0], walk_state);
127 : 22 : break;
128 : :
129 : 0 : case AML_RESET_OP: /* Reset (event_object) */
130 : :
131 : 0 : status = acpi_ex_system_reset_event(operand[0]);
132 : 0 : break;
133 : :
134 : 0 : case AML_SIGNAL_OP: /* Signal (event_object) */
135 : :
136 : 0 : status = acpi_ex_system_signal_event(operand[0]);
137 : 0 : break;
138 : :
139 : 0 : case AML_SLEEP_OP: /* Sleep (msec_time) */
140 : :
141 : 0 : status = acpi_ex_system_do_sleep(operand[0]->integer.value);
142 : 0 : break;
143 : :
144 : 0 : case AML_STALL_OP: /* Stall (usec_time) */
145 : :
146 : 0 : status =
147 : 0 : acpi_ex_system_do_stall((u32) operand[0]->integer.value);
148 : 0 : break;
149 : :
150 : 0 : case AML_UNLOAD_OP: /* Unload (Handle) */
151 : :
152 : 0 : status = acpi_ex_unload_table(operand[0]);
153 : 0 : break;
154 : :
155 : 0 : default: /* Unknown opcode */
156 : :
157 : 0 : ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
158 : : walk_state->opcode));
159 : 0 : status = AE_AML_BAD_OPCODE;
160 : 0 : break;
161 : : }
162 : :
163 : 22 : return_ACPI_STATUS(status);
164 : : }
165 : :
166 : : /*******************************************************************************
167 : : *
168 : : * FUNCTION: acpi_ex_opcode_1A_1T_0R
169 : : *
170 : : * PARAMETERS: walk_state - Current state (contains AML opcode)
171 : : *
172 : : * RETURN: Status
173 : : *
174 : : * DESCRIPTION: Execute opcode with one argument, one target, and no
175 : : * return value.
176 : : *
177 : : ******************************************************************************/
178 : :
179 : 0 : acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
180 : : {
181 : 0 : acpi_status status = AE_OK;
182 : 0 : union acpi_operand_object **operand = &walk_state->operands[0];
183 : :
184 : : ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R,
185 : 0 : acpi_ps_get_opcode_name(walk_state->opcode));
186 : :
187 : : /* Examine the AML opcode */
188 : :
189 [ # # ]: 0 : switch (walk_state->opcode) {
190 : 0 : case AML_LOAD_OP:
191 : :
192 : 0 : status = acpi_ex_load_op(operand[0], operand[1], walk_state);
193 : 0 : break;
194 : :
195 : 0 : default: /* Unknown opcode */
196 : :
197 : 0 : ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
198 : : walk_state->opcode));
199 : 0 : status = AE_AML_BAD_OPCODE;
200 : 0 : goto cleanup;
201 : : }
202 : :
203 : 0 : cleanup:
204 : :
205 : 0 : return_ACPI_STATUS(status);
206 : : }
207 : :
208 : : /*******************************************************************************
209 : : *
210 : : * FUNCTION: acpi_ex_opcode_1A_1T_1R
211 : : *
212 : : * PARAMETERS: walk_state - Current state (contains AML opcode)
213 : : *
214 : : * RETURN: Status
215 : : *
216 : : * DESCRIPTION: Execute opcode with one argument, one target, and a
217 : : * return value.
218 : : *
219 : : ******************************************************************************/
220 : :
221 : 17347 : acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
222 : : {
223 : 17347 : acpi_status status = AE_OK;
224 : 17347 : union acpi_operand_object **operand = &walk_state->operands[0];
225 : 17347 : union acpi_operand_object *return_desc = NULL;
226 : 17347 : union acpi_operand_object *return_desc2 = NULL;
227 : 17347 : u32 temp32;
228 : 17347 : u32 i;
229 : 17347 : u64 power_of_ten;
230 : 17347 : u64 digit;
231 : :
232 : : ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R,
233 : 17347 : acpi_ps_get_opcode_name(walk_state->opcode));
234 : :
235 : : /* Examine the AML opcode */
236 : :
237 [ - + - - : 17347 : switch (walk_state->opcode) {
- - - -
- ]
238 : 0 : case AML_BIT_NOT_OP:
239 : : case AML_FIND_SET_LEFT_BIT_OP:
240 : : case AML_FIND_SET_RIGHT_BIT_OP:
241 : : case AML_FROM_BCD_OP:
242 : : case AML_TO_BCD_OP:
243 : : case AML_CONDITIONAL_REF_OF_OP:
244 : :
245 : : /* Create a return object of type Integer for these opcodes */
246 : :
247 : 0 : return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
248 [ # # ]: 0 : if (!return_desc) {
249 : 0 : status = AE_NO_MEMORY;
250 : 0 : goto cleanup;
251 : : }
252 : :
253 [ # # # # : 0 : switch (walk_state->opcode) {
# # # ]
254 : 0 : case AML_BIT_NOT_OP: /* Not (Operand, Result) */
255 : :
256 : 0 : return_desc->integer.value = ~operand[0]->integer.value;
257 : 0 : break;
258 : :
259 : 0 : case AML_FIND_SET_LEFT_BIT_OP: /* find_set_left_bit (Operand, Result) */
260 : :
261 : 0 : return_desc->integer.value = operand[0]->integer.value;
262 : :
263 : : /*
264 : : * Acpi specification describes Integer type as a little
265 : : * endian unsigned value, so this boundary condition is valid.
266 : : */
267 [ # # ]: 0 : for (temp32 = 0; return_desc->integer.value &&
268 [ # # ]: 0 : temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
269 : 0 : return_desc->integer.value >>= 1;
270 : : }
271 : :
272 : 0 : return_desc->integer.value = temp32;
273 : 0 : break;
274 : :
275 : 0 : case AML_FIND_SET_RIGHT_BIT_OP: /* find_set_right_bit (Operand, Result) */
276 : :
277 : 0 : return_desc->integer.value = operand[0]->integer.value;
278 : :
279 : : /*
280 : : * The Acpi specification describes Integer type as a little
281 : : * endian unsigned value, so this boundary condition is valid.
282 : : */
283 [ # # ]: 0 : for (temp32 = 0; return_desc->integer.value &&
284 [ # # ]: 0 : temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
285 : 0 : return_desc->integer.value <<= 1;
286 : : }
287 : :
288 : : /* Since the bit position is one-based, subtract from 33 (65) */
289 : :
290 : 0 : return_desc->integer.value =
291 : 0 : temp32 ==
292 [ # # ]: 0 : 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - temp32;
293 : 0 : break;
294 : :
295 : 0 : case AML_FROM_BCD_OP: /* from_bcd (BCDValue, Result) */
296 : : /*
297 : : * The 64-bit ACPI integer can hold 16 4-bit BCD characters
298 : : * (if table is 32-bit, integer can hold 8 BCD characters)
299 : : * Convert each 4-bit BCD value
300 : : */
301 : 0 : power_of_ten = 1;
302 : 0 : return_desc->integer.value = 0;
303 : 0 : digit = operand[0]->integer.value;
304 : :
305 : : /* Convert each BCD digit (each is one nybble wide) */
306 : :
307 : 0 : for (i = 0;
308 [ # # # # ]: 0 : (i < acpi_gbl_integer_nybble_width) && (digit > 0);
309 : 0 : i++) {
310 : :
311 : : /* Get the least significant 4-bit BCD digit */
312 : :
313 : 0 : temp32 = ((u32) digit) & 0xF;
314 : :
315 : : /* Check the range of the digit */
316 : :
317 [ # # ]: 0 : if (temp32 > 9) {
318 : 0 : ACPI_ERROR((AE_INFO,
319 : : "BCD digit too large (not decimal): 0x%X",
320 : : temp32));
321 : :
322 : 0 : status = AE_AML_NUMERIC_OVERFLOW;
323 : 0 : goto cleanup;
324 : : }
325 : :
326 : : /* Sum the digit into the result with the current power of 10 */
327 : :
328 : 0 : return_desc->integer.value +=
329 : 0 : (((u64) temp32) * power_of_ten);
330 : :
331 : : /* Shift to next BCD digit */
332 : :
333 : 0 : digit >>= 4;
334 : :
335 : : /* Next power of 10 */
336 : :
337 : 0 : power_of_ten *= 10;
338 : : }
339 : : break;
340 : :
341 : 0 : case AML_TO_BCD_OP: /* to_bcd (Operand, Result) */
342 : :
343 : 0 : return_desc->integer.value = 0;
344 : 0 : digit = operand[0]->integer.value;
345 : :
346 : : /* Each BCD digit is one nybble wide */
347 : :
348 : 0 : for (i = 0;
349 [ # # # # ]: 0 : (i < acpi_gbl_integer_nybble_width) && (digit > 0);
350 : 0 : i++) {
351 : 0 : (void)acpi_ut_short_divide(digit, 10, &digit,
352 : : &temp32);
353 : :
354 : : /*
355 : : * Insert the BCD digit that resides in the
356 : : * remainder from above
357 : : */
358 : 0 : return_desc->integer.value |=
359 : 0 : (((u64) temp32) << ACPI_MUL_4(i));
360 : : }
361 : :
362 : : /* Overflow if there is any data left in Digit */
363 : :
364 [ # # ]: 0 : if (digit > 0) {
365 : 0 : ACPI_ERROR((AE_INFO,
366 : : "Integer too large to convert to BCD: 0x%8.8X%8.8X",
367 : : ACPI_FORMAT_UINT64(operand[0]->
368 : : integer.value)));
369 : 0 : status = AE_AML_NUMERIC_OVERFLOW;
370 : 0 : goto cleanup;
371 : : }
372 : : break;
373 : :
374 : 0 : case AML_CONDITIONAL_REF_OF_OP: /* cond_ref_of (source_object, Result) */
375 : : /*
376 : : * This op is a little strange because the internal return value is
377 : : * different than the return value stored in the result descriptor
378 : : * (There are really two return values)
379 : : */
380 [ # # ]: 0 : if ((struct acpi_namespace_node *)operand[0] ==
381 : : acpi_gbl_root_node) {
382 : : /*
383 : : * This means that the object does not exist in the namespace,
384 : : * return FALSE
385 : : */
386 : 0 : return_desc->integer.value = 0;
387 : 0 : goto cleanup;
388 : : }
389 : :
390 : : /* Get the object reference, store it, and remove our reference */
391 : :
392 : 0 : status = acpi_ex_get_object_reference(operand[0],
393 : : &return_desc2,
394 : : walk_state);
395 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
396 : 0 : goto cleanup;
397 : : }
398 : :
399 : 0 : status =
400 : 0 : acpi_ex_store(return_desc2, operand[1], walk_state);
401 : 0 : acpi_ut_remove_reference(return_desc2);
402 : :
403 : : /* The object exists in the namespace, return TRUE */
404 : :
405 : 0 : return_desc->integer.value = ACPI_UINT64_MAX;
406 : 0 : goto cleanup;
407 : :
408 : : default:
409 : :
410 : : /* No other opcodes get here */
411 : :
412 : : break;
413 : : }
414 : : break;
415 : :
416 : 17347 : case AML_STORE_OP: /* Store (Source, Target) */
417 : : /*
418 : : * A store operand is typically a number, string, buffer or lvalue
419 : : * Be careful about deleting the source object,
420 : : * since the object itself may have been stored.
421 : : */
422 : 17347 : status = acpi_ex_store(operand[0], operand[1], walk_state);
423 [ + - ]: 17347 : if (ACPI_FAILURE(status)) {
424 : : return_ACPI_STATUS(status);
425 : : }
426 : :
427 : : /* It is possible that the Store already produced a return object */
428 : :
429 [ + - ]: 17347 : if (!walk_state->result_obj) {
430 : : /*
431 : : * Normally, we would remove a reference on the Operand[0]
432 : : * parameter; But since it is being used as the internal return
433 : : * object (meaning we would normally increment it), the two
434 : : * cancel out, and we simply don't do anything.
435 : : */
436 : 17347 : walk_state->result_obj = operand[0];
437 : 17347 : walk_state->operands[0] = NULL; /* Prevent deletion */
438 : : }
439 : : return_ACPI_STATUS(status);
440 : :
441 : : /*
442 : : * ACPI 2.0 Opcodes
443 : : */
444 : 0 : case AML_COPY_OBJECT_OP: /* copy_object (Source, Target) */
445 : :
446 : 0 : status =
447 : 0 : acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,
448 : : walk_state);
449 : 0 : break;
450 : :
451 : 0 : case AML_TO_DECIMAL_STRING_OP: /* to_decimal_string (Data, Result) */
452 : :
453 : 0 : status =
454 : 0 : acpi_ex_convert_to_string(operand[0], &return_desc,
455 : : ACPI_EXPLICIT_CONVERT_DECIMAL);
456 [ # # ]: 0 : if (return_desc == operand[0]) {
457 : :
458 : : /* No conversion performed, add ref to handle return value */
459 : :
460 : 0 : acpi_ut_add_reference(return_desc);
461 : : }
462 : : break;
463 : :
464 : 0 : case AML_TO_HEX_STRING_OP: /* to_hex_string (Data, Result) */
465 : :
466 : 0 : status =
467 : 0 : acpi_ex_convert_to_string(operand[0], &return_desc,
468 : : ACPI_EXPLICIT_CONVERT_HEX);
469 [ # # ]: 0 : if (return_desc == operand[0]) {
470 : :
471 : : /* No conversion performed, add ref to handle return value */
472 : :
473 : 0 : acpi_ut_add_reference(return_desc);
474 : : }
475 : : break;
476 : :
477 : 0 : case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
478 : :
479 : 0 : status = acpi_ex_convert_to_buffer(operand[0], &return_desc);
480 [ # # ]: 0 : if (return_desc == operand[0]) {
481 : :
482 : : /* No conversion performed, add ref to handle return value */
483 : :
484 : 0 : acpi_ut_add_reference(return_desc);
485 : : }
486 : : break;
487 : :
488 : 0 : case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
489 : :
490 : : /* Perform "explicit" conversion */
491 : :
492 : 0 : status =
493 : 0 : acpi_ex_convert_to_integer(operand[0], &return_desc, 0);
494 [ # # ]: 0 : if (return_desc == operand[0]) {
495 : :
496 : : /* No conversion performed, add ref to handle return value */
497 : :
498 : 0 : acpi_ut_add_reference(return_desc);
499 : : }
500 : : break;
501 : :
502 : 0 : case AML_SHIFT_LEFT_BIT_OP: /* shift_left_bit (Source, bit_num) */
503 : : case AML_SHIFT_RIGHT_BIT_OP: /* shift_right_bit (Source, bit_num) */
504 : :
505 : : /* These are two obsolete opcodes */
506 : :
507 : 0 : ACPI_ERROR((AE_INFO,
508 : : "%s is obsolete and not implemented",
509 : : acpi_ps_get_opcode_name(walk_state->opcode)));
510 : 0 : status = AE_SUPPORT;
511 : 0 : goto cleanup;
512 : :
513 : 0 : default: /* Unknown opcode */
514 : :
515 : 0 : ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
516 : : walk_state->opcode));
517 : 0 : status = AE_AML_BAD_OPCODE;
518 : 0 : goto cleanup;
519 : : }
520 : :
521 [ # # ]: 0 : if (ACPI_SUCCESS(status)) {
522 : :
523 : : /* Store the return value computed above into the target object */
524 : :
525 : 0 : status = acpi_ex_store(return_desc, operand[1], walk_state);
526 : : }
527 : :
528 : 0 : cleanup:
529 : :
530 : : /* Delete return object on error */
531 : :
532 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
533 : 0 : acpi_ut_remove_reference(return_desc);
534 : : }
535 : :
536 : : /* Save return object on success */
537 : :
538 [ # # ]: 0 : else if (!walk_state->result_obj) {
539 : 0 : walk_state->result_obj = return_desc;
540 : : }
541 : :
542 : : return_ACPI_STATUS(status);
543 : : }
544 : :
545 : : /*******************************************************************************
546 : : *
547 : : * FUNCTION: acpi_ex_opcode_1A_0T_1R
548 : : *
549 : : * PARAMETERS: walk_state - Current state (contains AML opcode)
550 : : *
551 : : * RETURN: Status
552 : : *
553 : : * DESCRIPTION: Execute opcode with one argument, no target, and a return value
554 : : *
555 : : ******************************************************************************/
556 : :
557 : 2816 : acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
558 : : {
559 : 2816 : union acpi_operand_object **operand = &walk_state->operands[0];
560 : 2816 : union acpi_operand_object *temp_desc;
561 : 2816 : union acpi_operand_object *return_desc = NULL;
562 : 2816 : acpi_status status = AE_OK;
563 : 2816 : u32 type;
564 : 2816 : u64 value;
565 : :
566 : : ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R,
567 : 2816 : acpi_ps_get_opcode_name(walk_state->opcode));
568 : :
569 : : /* Examine the AML opcode */
570 : :
571 [ - + - - : 2816 : switch (walk_state->opcode) {
- - - ]
572 : 0 : case AML_LOGICAL_NOT_OP: /* LNot (Operand) */
573 : :
574 : 0 : return_desc = acpi_ut_create_integer_object((u64) 0);
575 [ # # ]: 0 : if (!return_desc) {
576 : 0 : status = AE_NO_MEMORY;
577 : 0 : goto cleanup;
578 : : }
579 : :
580 : : /*
581 : : * Set result to ONES (TRUE) if Value == 0. Note:
582 : : * return_desc->Integer.Value is initially == 0 (FALSE) from above.
583 : : */
584 [ # # ]: 0 : if (!operand[0]->integer.value) {
585 : 0 : return_desc->integer.value = ACPI_UINT64_MAX;
586 : : }
587 : : break;
588 : :
589 : 2816 : case AML_DECREMENT_OP: /* Decrement (Operand) */
590 : : case AML_INCREMENT_OP: /* Increment (Operand) */
591 : : /*
592 : : * Create a new integer. Can't just get the base integer and
593 : : * increment it because it may be an Arg or Field.
594 : : */
595 : 2816 : return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
596 [ - + ]: 2816 : if (!return_desc) {
597 : 0 : status = AE_NO_MEMORY;
598 : 0 : goto cleanup;
599 : : }
600 : :
601 : : /*
602 : : * Since we are expecting a Reference operand, it can be either a
603 : : * NS Node or an internal object.
604 : : */
605 : 2816 : temp_desc = operand[0];
606 [ + - ]: 2816 : if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
607 : : ACPI_DESC_TYPE_OPERAND) {
608 : :
609 : : /* Internal reference object - prevent deletion */
610 : :
611 : 2816 : acpi_ut_add_reference(temp_desc);
612 : : }
613 : :
614 : : /*
615 : : * Convert the Reference operand to an Integer (This removes a
616 : : * reference on the Operand[0] object)
617 : : *
618 : : * NOTE: We use LNOT_OP here in order to force resolution of the
619 : : * reference operand to an actual integer.
620 : : */
621 : 2816 : status = acpi_ex_resolve_operands(AML_LOGICAL_NOT_OP,
622 : : &temp_desc, walk_state);
623 [ - + ]: 2816 : if (ACPI_FAILURE(status)) {
624 : 0 : ACPI_EXCEPTION((AE_INFO, status,
625 : : "While resolving operands for [%s]",
626 : : acpi_ps_get_opcode_name(walk_state->
627 : : opcode)));
628 : :
629 : 0 : goto cleanup;
630 : : }
631 : :
632 : : /*
633 : : * temp_desc is now guaranteed to be an Integer object --
634 : : * Perform the actual increment or decrement
635 : : */
636 [ + - ]: 2816 : if (walk_state->opcode == AML_INCREMENT_OP) {
637 : 2816 : return_desc->integer.value =
638 : 2816 : temp_desc->integer.value + 1;
639 : : } else {
640 : 0 : return_desc->integer.value =
641 : 0 : temp_desc->integer.value - 1;
642 : : }
643 : :
644 : : /* Finished with this Integer object */
645 : :
646 : 2816 : acpi_ut_remove_reference(temp_desc);
647 : :
648 : : /*
649 : : * Store the result back (indirectly) through the original
650 : : * Reference object
651 : : */
652 : 2816 : status = acpi_ex_store(return_desc, operand[0], walk_state);
653 : 2816 : break;
654 : :
655 : 0 : case AML_OBJECT_TYPE_OP: /* object_type (source_object) */
656 : : /*
657 : : * Note: The operand is not resolved at this point because we want to
658 : : * get the associated object, not its value. For example, we don't
659 : : * want to resolve a field_unit to its value, we want the actual
660 : : * field_unit object.
661 : : */
662 : :
663 : : /* Get the type of the base object */
664 : :
665 : 0 : status =
666 : 0 : acpi_ex_resolve_multiple(walk_state, operand[0], &type,
667 : : NULL);
668 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
669 : 0 : goto cleanup;
670 : : }
671 : :
672 : : /* Allocate a descriptor to hold the type. */
673 : :
674 : 0 : return_desc = acpi_ut_create_integer_object((u64) type);
675 [ # # ]: 0 : if (!return_desc) {
676 : 0 : status = AE_NO_MEMORY;
677 : 0 : goto cleanup;
678 : : }
679 : : break;
680 : :
681 : 0 : case AML_SIZE_OF_OP: /* size_of (source_object) */
682 : : /*
683 : : * Note: The operand is not resolved at this point because we want to
684 : : * get the associated object, not its value.
685 : : */
686 : :
687 : : /* Get the base object */
688 : :
689 : 0 : status =
690 : 0 : acpi_ex_resolve_multiple(walk_state, operand[0], &type,
691 : : &temp_desc);
692 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
693 : 0 : goto cleanup;
694 : : }
695 : :
696 : : /*
697 : : * The type of the base object must be integer, buffer, string, or
698 : : * package. All others are not supported.
699 : : *
700 : : * NOTE: Integer is not specifically supported by the ACPI spec,
701 : : * but is supported implicitly via implicit operand conversion.
702 : : * rather than bother with conversion, we just use the byte width
703 : : * global (4 or 8 bytes).
704 : : */
705 [ # # # # : 0 : switch (type) {
# ]
706 : 0 : case ACPI_TYPE_INTEGER:
707 : :
708 : 0 : value = acpi_gbl_integer_byte_width;
709 : 0 : break;
710 : :
711 : 0 : case ACPI_TYPE_STRING:
712 : :
713 : 0 : value = temp_desc->string.length;
714 : 0 : break;
715 : :
716 : 0 : case ACPI_TYPE_BUFFER:
717 : :
718 : : /* Buffer arguments may not be evaluated at this point */
719 : :
720 : 0 : status = acpi_ds_get_buffer_arguments(temp_desc);
721 : 0 : value = temp_desc->buffer.length;
722 : 0 : break;
723 : :
724 : 0 : case ACPI_TYPE_PACKAGE:
725 : :
726 : : /* Package arguments may not be evaluated at this point */
727 : :
728 : 0 : status = acpi_ds_get_package_arguments(temp_desc);
729 : 0 : value = temp_desc->package.count;
730 : 0 : break;
731 : :
732 : 0 : default:
733 : :
734 : 0 : ACPI_ERROR((AE_INFO,
735 : : "Operand must be Buffer/Integer/String/Package"
736 : : " - found type %s",
737 : : acpi_ut_get_type_name(type)));
738 : :
739 : 0 : status = AE_AML_OPERAND_TYPE;
740 : 0 : goto cleanup;
741 : : }
742 : :
743 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
744 : 0 : goto cleanup;
745 : : }
746 : :
747 : : /*
748 : : * Now that we have the size of the object, create a result
749 : : * object to hold the value
750 : : */
751 : 0 : return_desc = acpi_ut_create_integer_object(value);
752 [ # # ]: 0 : if (!return_desc) {
753 : 0 : status = AE_NO_MEMORY;
754 : 0 : goto cleanup;
755 : : }
756 : : break;
757 : :
758 : 0 : case AML_REF_OF_OP: /* ref_of (source_object) */
759 : :
760 : 0 : status =
761 : 0 : acpi_ex_get_object_reference(operand[0], &return_desc,
762 : : walk_state);
763 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
764 : 0 : goto cleanup;
765 : : }
766 : : break;
767 : :
768 : 0 : case AML_DEREF_OF_OP: /* deref_of (obj_reference | String) */
769 : :
770 : : /* Check for a method local or argument, or standalone String */
771 : :
772 [ # # ]: 0 : if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
773 : : ACPI_DESC_TYPE_NAMED) {
774 : 0 : temp_desc =
775 : 0 : acpi_ns_get_attached_object((struct
776 : : acpi_namespace_node *)
777 : : operand[0]);
778 [ # # ]: 0 : if (temp_desc
779 : 0 : && ((temp_desc->common.type == ACPI_TYPE_STRING)
780 [ # # ]: 0 : || (temp_desc->common.type ==
781 : : ACPI_TYPE_LOCAL_REFERENCE))) {
782 : 0 : operand[0] = temp_desc;
783 : 0 : acpi_ut_add_reference(temp_desc);
784 : : } else {
785 : 0 : status = AE_AML_OPERAND_TYPE;
786 : 0 : goto cleanup;
787 : : }
788 : : } else {
789 [ # # # ]: 0 : switch ((operand[0])->common.type) {
790 : 0 : case ACPI_TYPE_LOCAL_REFERENCE:
791 : : /*
792 : : * This is a deref_of (local_x | arg_x)
793 : : *
794 : : * Must resolve/dereference the local/arg reference first
795 : : */
796 [ # # # ]: 0 : switch (operand[0]->reference.class) {
797 : 0 : case ACPI_REFCLASS_LOCAL:
798 : : case ACPI_REFCLASS_ARG:
799 : :
800 : : /* Set Operand[0] to the value of the local/arg */
801 : :
802 : 0 : status =
803 : 0 : acpi_ds_method_data_get_value
804 : : (operand[0]->reference.class,
805 : : operand[0]->reference.value,
806 : : walk_state, &temp_desc);
807 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
808 : 0 : goto cleanup;
809 : : }
810 : :
811 : : /*
812 : : * Delete our reference to the input object and
813 : : * point to the object just retrieved
814 : : */
815 : 0 : acpi_ut_remove_reference(operand[0]);
816 : 0 : operand[0] = temp_desc;
817 : 0 : break;
818 : :
819 : 0 : case ACPI_REFCLASS_REFOF:
820 : :
821 : : /* Get the object to which the reference refers */
822 : :
823 : 0 : temp_desc =
824 : 0 : operand[0]->reference.object;
825 : 0 : acpi_ut_remove_reference(operand[0]);
826 : 0 : operand[0] = temp_desc;
827 : 0 : break;
828 : :
829 : : default:
830 : :
831 : : /* Must be an Index op - handled below */
832 : : break;
833 : : }
834 : : break;
835 : :
836 : : case ACPI_TYPE_STRING:
837 : :
838 : : break;
839 : :
840 : 0 : default:
841 : :
842 : 0 : status = AE_AML_OPERAND_TYPE;
843 : 0 : goto cleanup;
844 : : }
845 : : }
846 : :
847 [ # # ]: 0 : if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
848 : : ACPI_DESC_TYPE_NAMED) {
849 [ # # ]: 0 : if ((operand[0])->common.type == ACPI_TYPE_STRING) {
850 : : /*
851 : : * This is a deref_of (String). The string is a reference
852 : : * to a named ACPI object.
853 : : *
854 : : * 1) Find the owning Node
855 : : * 2) Dereference the node to an actual object. Could be a
856 : : * Field, so we need to resolve the node to a value.
857 : : */
858 : 0 : status =
859 : 0 : acpi_ns_get_node_unlocked(walk_state->
860 : : scope_info->scope.
861 : : node,
862 : : operand[0]->
863 : 0 : string.pointer,
864 : : ACPI_NS_SEARCH_PARENT,
865 : : ACPI_CAST_INDIRECT_PTR
866 : : (struct
867 : : acpi_namespace_node,
868 : : &return_desc));
869 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
870 : 0 : goto cleanup;
871 : : }
872 : :
873 : 0 : status =
874 : 0 : acpi_ex_resolve_node_to_value
875 : : (ACPI_CAST_INDIRECT_PTR
876 : : (struct acpi_namespace_node, &return_desc),
877 : : walk_state);
878 : 0 : goto cleanup;
879 : : }
880 : : }
881 : :
882 : : /* Operand[0] may have changed from the code above */
883 : :
884 [ # # ]: 0 : if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
885 : : ACPI_DESC_TYPE_NAMED) {
886 : : /*
887 : : * This is a deref_of (object_reference)
888 : : * Get the actual object from the Node (This is the dereference).
889 : : * This case may only happen when a local_x or arg_x is
890 : : * dereferenced above, or for references to device and
891 : : * thermal objects.
892 : : */
893 [ # # ]: 0 : switch (((struct acpi_namespace_node *)operand[0])->
894 : : type) {
895 : 0 : case ACPI_TYPE_DEVICE:
896 : : case ACPI_TYPE_THERMAL:
897 : :
898 : : /* These types have no node subobject, return the NS node */
899 : :
900 : 0 : return_desc = operand[0];
901 : 0 : break;
902 : :
903 : 0 : default:
904 : : /* For most types, get the object attached to the node */
905 : :
906 : 0 : return_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)operand[0]);
907 : 0 : acpi_ut_add_reference(return_desc);
908 : 0 : break;
909 : : }
910 : : } else {
911 : : /*
912 : : * This must be a reference object produced by either the
913 : : * Index() or ref_of() operator
914 : : */
915 [ # # # ]: 0 : switch (operand[0]->reference.class) {
916 : 0 : case ACPI_REFCLASS_INDEX:
917 : : /*
918 : : * The target type for the Index operator must be
919 : : * either a Buffer or a Package
920 : : */
921 [ # # # ]: 0 : switch (operand[0]->reference.target_type) {
922 : 0 : case ACPI_TYPE_BUFFER_FIELD:
923 : :
924 : 0 : temp_desc =
925 : 0 : operand[0]->reference.object;
926 : :
927 : : /*
928 : : * Create a new object that contains one element of the
929 : : * buffer -- the element pointed to by the index.
930 : : *
931 : : * NOTE: index into a buffer is NOT a pointer to a
932 : : * sub-buffer of the main buffer, it is only a pointer to a
933 : : * single element (byte) of the buffer!
934 : : *
935 : : * Since we are returning the value of the buffer at the
936 : : * indexed location, we don't need to add an additional
937 : : * reference to the buffer itself.
938 : : */
939 : 0 : return_desc =
940 : 0 : acpi_ut_create_integer_object((u64)
941 : 0 : temp_desc->buffer.pointer[operand[0]->reference.value]);
942 [ # # ]: 0 : if (!return_desc) {
943 : 0 : status = AE_NO_MEMORY;
944 : 0 : goto cleanup;
945 : : }
946 : : break;
947 : :
948 : 0 : case ACPI_TYPE_PACKAGE:
949 : : /*
950 : : * Return the referenced element of the package. We must
951 : : * add another reference to the referenced object, however.
952 : : */
953 : 0 : return_desc =
954 : 0 : *(operand[0]->reference.where);
955 [ # # ]: 0 : if (!return_desc) {
956 : : /*
957 : : * Element is NULL, do not allow the dereference.
958 : : * This provides compatibility with other ACPI
959 : : * implementations.
960 : : */
961 : : return_ACPI_STATUS
962 : : (AE_AML_UNINITIALIZED_ELEMENT);
963 : : }
964 : :
965 : 0 : acpi_ut_add_reference(return_desc);
966 : 0 : break;
967 : :
968 : 0 : default:
969 : :
970 : 0 : ACPI_ERROR((AE_INFO,
971 : : "Unknown Index TargetType 0x%X in reference object %p",
972 : : operand[0]->reference.
973 : : target_type, operand[0]));
974 : :
975 : 0 : status = AE_AML_OPERAND_TYPE;
976 : 0 : goto cleanup;
977 : : }
978 : : break;
979 : :
980 : 0 : case ACPI_REFCLASS_REFOF:
981 : :
982 : 0 : return_desc = operand[0]->reference.object;
983 : :
984 [ # # ]: 0 : if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
985 : : ACPI_DESC_TYPE_NAMED) {
986 : 0 : return_desc =
987 : 0 : acpi_ns_get_attached_object((struct
988 : : acpi_namespace_node
989 : : *)
990 : : return_desc);
991 [ # # ]: 0 : if (!return_desc) {
992 : : break;
993 : : }
994 : :
995 : : /*
996 : : * June 2013:
997 : : * buffer_fields/field_units require additional resolution
998 : : */
999 [ # # ]: 0 : switch (return_desc->common.type) {
1000 : 0 : case ACPI_TYPE_BUFFER_FIELD:
1001 : : case ACPI_TYPE_LOCAL_REGION_FIELD:
1002 : : case ACPI_TYPE_LOCAL_BANK_FIELD:
1003 : : case ACPI_TYPE_LOCAL_INDEX_FIELD:
1004 : :
1005 : 0 : status =
1006 : 0 : acpi_ex_read_data_from_field
1007 : : (walk_state, return_desc,
1008 : : &temp_desc);
1009 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
1010 : 0 : goto cleanup;
1011 : : }
1012 : :
1013 : 0 : return_desc = temp_desc;
1014 : 0 : break;
1015 : :
1016 : 0 : default:
1017 : :
1018 : : /* Add another reference to the object */
1019 : :
1020 : 0 : acpi_ut_add_reference
1021 : : (return_desc);
1022 : 0 : break;
1023 : : }
1024 : 0 : }
1025 : : break;
1026 : :
1027 : 0 : default:
1028 : :
1029 : 0 : ACPI_ERROR((AE_INFO,
1030 : : "Unknown class in reference(%p) - 0x%2.2X",
1031 : : operand[0],
1032 : : operand[0]->reference.class));
1033 : :
1034 : 0 : status = AE_TYPE;
1035 : 0 : goto cleanup;
1036 : : }
1037 : 0 : }
1038 : : break;
1039 : :
1040 : 0 : default:
1041 : :
1042 : 0 : ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
1043 : : walk_state->opcode));
1044 : :
1045 : 0 : status = AE_AML_BAD_OPCODE;
1046 : 0 : goto cleanup;
1047 : : }
1048 : :
1049 : 2816 : cleanup:
1050 : :
1051 : : /* Delete return object on error */
1052 : :
1053 [ - + ]: 2816 : if (ACPI_FAILURE(status)) {
1054 : 0 : acpi_ut_remove_reference(return_desc);
1055 : : }
1056 : :
1057 : : /* Save return object on success */
1058 : :
1059 : : else {
1060 : 2816 : walk_state->result_obj = return_desc;
1061 : : }
1062 : :
1063 : : return_ACPI_STATUS(status);
1064 : : }
|