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