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