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