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