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