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