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