xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/executer/exoparg1.c (revision a5a3b2d9a3d95cbae71eaf371708c73a1780ac0d)
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 - 2016, 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 (
585             Operand[0], &ReturnDesc, WalkState);
586         break;
587 
588     case AML_TO_DECSTRING_OP:       /* ToDecimalString (Data, Result) */
589 
590         Status = AcpiExConvertToString (
591             Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_DECIMAL);
592         if (ReturnDesc == Operand[0])
593         {
594             /* No conversion performed, add ref to handle return value */
595 
596             AcpiUtAddReference (ReturnDesc);
597         }
598         break;
599 
600     case AML_TO_HEXSTRING_OP:       /* ToHexString (Data, Result) */
601 
602         Status = AcpiExConvertToString (
603             Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_HEX);
604         if (ReturnDesc == Operand[0])
605         {
606             /* No conversion performed, add ref to handle return value */
607 
608             AcpiUtAddReference (ReturnDesc);
609         }
610         break;
611 
612     case AML_TO_BUFFER_OP:          /* ToBuffer (Data, Result) */
613 
614         Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc);
615         if (ReturnDesc == Operand[0])
616         {
617             /* No conversion performed, add ref to handle return value */
618 
619             AcpiUtAddReference (ReturnDesc);
620         }
621         break;
622 
623     case AML_TO_INTEGER_OP:         /* ToInteger (Data, Result) */
624 
625         Status = AcpiExConvertToInteger (
626             Operand[0], &ReturnDesc, ACPI_ANY_BASE);
627         if (ReturnDesc == Operand[0])
628         {
629             /* No conversion performed, add ref to handle return value */
630 
631             AcpiUtAddReference (ReturnDesc);
632         }
633         break;
634 
635     case AML_SHIFT_LEFT_BIT_OP:     /* ShiftLeftBit (Source, BitNum)  */
636     case AML_SHIFT_RIGHT_BIT_OP:    /* ShiftRightBit (Source, BitNum) */
637 
638         /* These are two obsolete opcodes */
639 
640         ACPI_ERROR ((AE_INFO,
641             "%s is obsolete and not implemented",
642             AcpiPsGetOpcodeName (WalkState->Opcode)));
643         Status = AE_SUPPORT;
644         goto Cleanup;
645 
646     default:                        /* Unknown opcode */
647 
648         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
649             WalkState->Opcode));
650         Status = AE_AML_BAD_OPCODE;
651         goto Cleanup;
652     }
653 
654     if (ACPI_SUCCESS (Status))
655     {
656         /* Store the return value computed above into the target object */
657 
658         Status = AcpiExStore (ReturnDesc, Operand[1], WalkState);
659     }
660 
661 
662 Cleanup:
663 
664     /* Delete return object on error */
665 
666     if (ACPI_FAILURE (Status))
667     {
668         AcpiUtRemoveReference (ReturnDesc);
669     }
670 
671     /* Save return object on success */
672 
673     else if (!WalkState->ResultObj)
674     {
675         WalkState->ResultObj = ReturnDesc;
676     }
677 
678     return_ACPI_STATUS (Status);
679 }
680 
681 
682 /*******************************************************************************
683  *
684  * FUNCTION:    AcpiExOpcode_1A_0T_1R
685  *
686  * PARAMETERS:  WalkState           - Current state (contains AML opcode)
687  *
688  * RETURN:      Status
689  *
690  * DESCRIPTION: Execute opcode with one argument, no target, and a return value
691  *
692  ******************************************************************************/
693 
694 ACPI_STATUS
695 AcpiExOpcode_1A_0T_1R (
696     ACPI_WALK_STATE         *WalkState)
697 {
698     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
699     ACPI_OPERAND_OBJECT     *TempDesc;
700     ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
701     ACPI_STATUS             Status = AE_OK;
702     UINT32                  Type;
703     UINT64                  Value;
704 
705 
706     ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R,
707         AcpiPsGetOpcodeName (WalkState->Opcode));
708 
709 
710     /* Examine the AML opcode */
711 
712     switch (WalkState->Opcode)
713     {
714     case AML_LNOT_OP:               /* LNot (Operand) */
715 
716         ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0);
717         if (!ReturnDesc)
718         {
719             Status = AE_NO_MEMORY;
720             goto Cleanup;
721         }
722 
723         /*
724          * Set result to ONES (TRUE) if Value == 0. Note:
725          * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above.
726          */
727         if (!Operand[0]->Integer.Value)
728         {
729             ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
730         }
731         break;
732 
733     case AML_DECREMENT_OP:          /* Decrement (Operand)  */
734     case AML_INCREMENT_OP:          /* Increment (Operand)  */
735         /*
736          * Create a new integer. Can't just get the base integer and
737          * increment it because it may be an Arg or Field.
738          */
739         ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
740         if (!ReturnDesc)
741         {
742             Status = AE_NO_MEMORY;
743             goto Cleanup;
744         }
745 
746         /*
747          * Since we are expecting a Reference operand, it can be either a
748          * NS Node or an internal object.
749          */
750         TempDesc = Operand[0];
751         if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND)
752         {
753             /* Internal reference object - prevent deletion */
754 
755             AcpiUtAddReference (TempDesc);
756         }
757 
758         /*
759          * Convert the Reference operand to an Integer (This removes a
760          * reference on the Operand[0] object)
761          *
762          * NOTE:  We use LNOT_OP here in order to force resolution of the
763          * reference operand to an actual integer.
764          */
765         Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState);
766         if (ACPI_FAILURE (Status))
767         {
768             ACPI_EXCEPTION ((AE_INFO, Status,
769                 "While resolving operands for [%s]",
770                 AcpiPsGetOpcodeName (WalkState->Opcode)));
771 
772             goto Cleanup;
773         }
774 
775         /*
776          * TempDesc is now guaranteed to be an Integer object --
777          * Perform the actual increment or decrement
778          */
779         if (WalkState->Opcode == AML_INCREMENT_OP)
780         {
781             ReturnDesc->Integer.Value = TempDesc->Integer.Value + 1;
782         }
783         else
784         {
785             ReturnDesc->Integer.Value = TempDesc->Integer.Value - 1;
786         }
787 
788         /* Finished with this Integer object */
789 
790         AcpiUtRemoveReference (TempDesc);
791 
792         /*
793          * Store the result back (indirectly) through the original
794          * Reference object
795          */
796         Status = AcpiExStore (ReturnDesc, Operand[0], WalkState);
797         break;
798 
799     case AML_OBJECT_TYPE_OP:            /* ObjectType (SourceObject) */
800         /*
801          * Note: The operand is not resolved at this point because we want to
802          * get the associated object, not its value. For example, we don't
803          * want to resolve a FieldUnit to its value, we want the actual
804          * FieldUnit object.
805          */
806 
807         /* Get the type of the base object */
808 
809         Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL);
810         if (ACPI_FAILURE (Status))
811         {
812             goto Cleanup;
813         }
814 
815         /* Allocate a descriptor to hold the type. */
816 
817         ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type);
818         if (!ReturnDesc)
819         {
820             Status = AE_NO_MEMORY;
821             goto Cleanup;
822         }
823         break;
824 
825     case AML_SIZE_OF_OP:            /* SizeOf (SourceObject)  */
826         /*
827          * Note: The operand is not resolved at this point because we want to
828          * get the associated object, not its value.
829          */
830 
831         /* Get the base object */
832 
833         Status = AcpiExResolveMultiple (
834             WalkState, Operand[0], &Type, &TempDesc);
835         if (ACPI_FAILURE (Status))
836         {
837             goto Cleanup;
838         }
839 
840         /*
841          * The type of the base object must be integer, buffer, string, or
842          * package. All others are not supported.
843          *
844          * NOTE: Integer is not specifically supported by the ACPI spec,
845          * but is supported implicitly via implicit operand conversion.
846          * rather than bother with conversion, we just use the byte width
847          * global (4 or 8 bytes).
848          */
849         switch (Type)
850         {
851         case ACPI_TYPE_INTEGER:
852 
853             Value = AcpiGbl_IntegerByteWidth;
854             break;
855 
856         case ACPI_TYPE_STRING:
857 
858             Value = TempDesc->String.Length;
859             break;
860 
861         case ACPI_TYPE_BUFFER:
862 
863             /* Buffer arguments may not be evaluated at this point */
864 
865             Status = AcpiDsGetBufferArguments (TempDesc);
866             Value = TempDesc->Buffer.Length;
867             break;
868 
869         case ACPI_TYPE_PACKAGE:
870 
871             /* Package arguments may not be evaluated at this point */
872 
873             Status = AcpiDsGetPackageArguments (TempDesc);
874             Value = TempDesc->Package.Count;
875             break;
876 
877         default:
878 
879             ACPI_ERROR ((AE_INFO,
880                 "Operand must be Buffer/Integer/String/Package"
881                 " - found type %s",
882                 AcpiUtGetTypeName (Type)));
883 
884             Status = AE_AML_OPERAND_TYPE;
885             goto Cleanup;
886         }
887 
888         if (ACPI_FAILURE (Status))
889         {
890             goto Cleanup;
891         }
892 
893         /*
894          * Now that we have the size of the object, create a result
895          * object to hold the value
896          */
897         ReturnDesc = AcpiUtCreateIntegerObject (Value);
898         if (!ReturnDesc)
899         {
900             Status = AE_NO_MEMORY;
901             goto Cleanup;
902         }
903         break;
904 
905 
906     case AML_REF_OF_OP:             /* RefOf (SourceObject) */
907 
908         Status = AcpiExGetObjectReference (
909             Operand[0], &ReturnDesc, WalkState);
910         if (ACPI_FAILURE (Status))
911         {
912             goto Cleanup;
913         }
914         break;
915 
916 
917     case AML_DEREF_OF_OP:           /* DerefOf (ObjReference | String) */
918 
919         /* Check for a method local or argument, or standalone String */
920 
921         if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
922         {
923             TempDesc = AcpiNsGetAttachedObject (
924                            (ACPI_NAMESPACE_NODE *) Operand[0]);
925             if (TempDesc &&
926                  ((TempDesc->Common.Type == ACPI_TYPE_STRING) ||
927                   (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)))
928             {
929                 Operand[0] = TempDesc;
930                 AcpiUtAddReference (TempDesc);
931             }
932             else
933             {
934                 Status = AE_AML_OPERAND_TYPE;
935                 goto Cleanup;
936             }
937         }
938         else
939         {
940             switch ((Operand[0])->Common.Type)
941             {
942             case ACPI_TYPE_LOCAL_REFERENCE:
943                 /*
944                  * This is a DerefOf (LocalX | ArgX)
945                  *
946                  * Must resolve/dereference the local/arg reference first
947                  */
948                 switch (Operand[0]->Reference.Class)
949                 {
950                 case ACPI_REFCLASS_LOCAL:
951                 case ACPI_REFCLASS_ARG:
952 
953                     /* Set Operand[0] to the value of the local/arg */
954 
955                     Status = AcpiDsMethodDataGetValue (
956                         Operand[0]->Reference.Class,
957                         Operand[0]->Reference.Value,
958                         WalkState, &TempDesc);
959                     if (ACPI_FAILURE (Status))
960                     {
961                         goto Cleanup;
962                     }
963 
964                     /*
965                      * Delete our reference to the input object and
966                      * point to the object just retrieved
967                      */
968                     AcpiUtRemoveReference (Operand[0]);
969                     Operand[0] = TempDesc;
970                     break;
971 
972                 case ACPI_REFCLASS_REFOF:
973 
974                     /* Get the object to which the reference refers */
975 
976                     TempDesc = Operand[0]->Reference.Object;
977                     AcpiUtRemoveReference (Operand[0]);
978                     Operand[0] = TempDesc;
979                     break;
980 
981                 default:
982 
983                     /* Must be an Index op - handled below */
984                     break;
985                 }
986                 break;
987 
988             case ACPI_TYPE_STRING:
989 
990                 break;
991 
992             default:
993 
994                 Status = AE_AML_OPERAND_TYPE;
995                 goto Cleanup;
996             }
997         }
998 
999         if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED)
1000         {
1001             if ((Operand[0])->Common.Type == ACPI_TYPE_STRING)
1002             {
1003                 /*
1004                  * This is a DerefOf (String). The string is a reference
1005                  * to a named ACPI object.
1006                  *
1007                  * 1) Find the owning Node
1008                  * 2) Dereference the node to an actual object. Could be a
1009                  *    Field, so we need to resolve the node to a value.
1010                  */
1011                 Status = AcpiNsGetNode (WalkState->ScopeInfo->Scope.Node,
1012                     Operand[0]->String.Pointer,
1013                     ACPI_NS_SEARCH_PARENT,
1014                     ACPI_CAST_INDIRECT_PTR (
1015                         ACPI_NAMESPACE_NODE, &ReturnDesc));
1016                 if (ACPI_FAILURE (Status))
1017                 {
1018                     goto Cleanup;
1019                 }
1020 
1021                 Status = AcpiExResolveNodeToValue (
1022                     ACPI_CAST_INDIRECT_PTR (
1023                         ACPI_NAMESPACE_NODE, &ReturnDesc),
1024                     WalkState);
1025                 goto Cleanup;
1026             }
1027         }
1028 
1029         /* Operand[0] may have changed from the code above */
1030 
1031         if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
1032         {
1033             /*
1034              * This is a DerefOf (ObjectReference)
1035              * Get the actual object from the Node (This is the dereference).
1036              * This case may only happen when a LocalX or ArgX is
1037              * dereferenced above.
1038              */
1039             ReturnDesc = AcpiNsGetAttachedObject (
1040                 (ACPI_NAMESPACE_NODE *) Operand[0]);
1041             AcpiUtAddReference (ReturnDesc);
1042         }
1043         else
1044         {
1045             /*
1046              * This must be a reference object produced by either the
1047              * Index() or RefOf() operator
1048              */
1049             switch (Operand[0]->Reference.Class)
1050             {
1051             case ACPI_REFCLASS_INDEX:
1052                 /*
1053                  * The target type for the Index operator must be
1054                  * either a Buffer or a Package
1055                  */
1056                 switch (Operand[0]->Reference.TargetType)
1057                 {
1058                 case ACPI_TYPE_BUFFER_FIELD:
1059 
1060                     TempDesc = Operand[0]->Reference.Object;
1061 
1062                     /*
1063                      * Create a new object that contains one element of the
1064                      * buffer -- the element pointed to by the index.
1065                      *
1066                      * NOTE: index into a buffer is NOT a pointer to a
1067                      * sub-buffer of the main buffer, it is only a pointer to a
1068                      * single element (byte) of the buffer!
1069                      *
1070                      * Since we are returning the value of the buffer at the
1071                      * indexed location, we don't need to add an additional
1072                      * reference to the buffer itself.
1073                      */
1074                     ReturnDesc = AcpiUtCreateIntegerObject ((UINT64)
1075                         TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]);
1076                     if (!ReturnDesc)
1077                     {
1078                         Status = AE_NO_MEMORY;
1079                         goto Cleanup;
1080                     }
1081                     break;
1082 
1083                 case ACPI_TYPE_PACKAGE:
1084                     /*
1085                      * Return the referenced element of the package. We must
1086                      * add another reference to the referenced object, however.
1087                      */
1088                     ReturnDesc = *(Operand[0]->Reference.Where);
1089                     if (!ReturnDesc)
1090                     {
1091                         /*
1092                          * Element is NULL, do not allow the dereference.
1093                          * This provides compatibility with other ACPI
1094                          * implementations.
1095                          */
1096                         return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT);
1097                     }
1098 
1099                     AcpiUtAddReference (ReturnDesc);
1100                     break;
1101 
1102                 default:
1103 
1104                     ACPI_ERROR ((AE_INFO,
1105                         "Unknown Index TargetType 0x%X in reference object %p",
1106                         Operand[0]->Reference.TargetType, Operand[0]));
1107 
1108                     Status = AE_AML_OPERAND_TYPE;
1109                     goto Cleanup;
1110                 }
1111                 break;
1112 
1113             case ACPI_REFCLASS_REFOF:
1114 
1115                 ReturnDesc = Operand[0]->Reference.Object;
1116 
1117                 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) ==
1118                     ACPI_DESC_TYPE_NAMED)
1119                 {
1120                     ReturnDesc = AcpiNsGetAttachedObject (
1121                         (ACPI_NAMESPACE_NODE *) ReturnDesc);
1122                     if (!ReturnDesc)
1123                     {
1124                         break;
1125                     }
1126 
1127                    /*
1128                     * June 2013:
1129                     * BufferFields/FieldUnits require additional resolution
1130                     */
1131                     switch (ReturnDesc->Common.Type)
1132                     {
1133                     case ACPI_TYPE_BUFFER_FIELD:
1134                     case ACPI_TYPE_LOCAL_REGION_FIELD:
1135                     case ACPI_TYPE_LOCAL_BANK_FIELD:
1136                     case ACPI_TYPE_LOCAL_INDEX_FIELD:
1137 
1138                         Status = AcpiExReadDataFromField (
1139                             WalkState, ReturnDesc, &TempDesc);
1140                         if (ACPI_FAILURE (Status))
1141                         {
1142                             goto Cleanup;
1143                         }
1144 
1145                         ReturnDesc = TempDesc;
1146                         break;
1147 
1148                     default:
1149 
1150                         /* Add another reference to the object */
1151 
1152                         AcpiUtAddReference (ReturnDesc);
1153                         break;
1154                     }
1155                 }
1156                 break;
1157 
1158             default:
1159 
1160                 ACPI_ERROR ((AE_INFO,
1161                     "Unknown class in reference(%p) - 0x%2.2X",
1162                     Operand[0], Operand[0]->Reference.Class));
1163 
1164                 Status = AE_TYPE;
1165                 goto Cleanup;
1166             }
1167         }
1168         break;
1169 
1170     default:
1171 
1172         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
1173             WalkState->Opcode));
1174 
1175         Status = AE_AML_BAD_OPCODE;
1176         goto Cleanup;
1177     }
1178 
1179 
1180 Cleanup:
1181 
1182     /* Delete return object on error */
1183 
1184     if (ACPI_FAILURE (Status))
1185     {
1186         AcpiUtRemoveReference (ReturnDesc);
1187     }
1188 
1189     /* Save return object on success */
1190 
1191     else
1192     {
1193         WalkState->ResultObj = ReturnDesc;
1194     }
1195 
1196     return_ACPI_STATUS (Status);
1197 }
1198