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