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