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