xref: /titanic_52/usr/src/uts/intel/io/acpica/executer/exoparg2.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
1db2bae30SDana Myers /******************************************************************************
2db2bae30SDana Myers  *
3db2bae30SDana Myers  * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
4db2bae30SDana Myers  *
5db2bae30SDana Myers  *****************************************************************************/
6db2bae30SDana Myers 
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
9db2bae30SDana Myers  * All rights reserved.
10db2bae30SDana Myers  *
1126f3cdf0SGordon Ross  * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross  * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross  * are met:
1426f3cdf0SGordon Ross  * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross  *    notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross  *    without modification.
1726f3cdf0SGordon Ross  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross  *    substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross  *    ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross  *    including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross  *    binary redistribution.
2226f3cdf0SGordon Ross  * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross  *    of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross  *    from this software without specific prior written permission.
25db2bae30SDana Myers  *
2626f3cdf0SGordon Ross  * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross  * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross  * Software Foundation.
29db2bae30SDana Myers  *
3026f3cdf0SGordon Ross  * NO WARRANTY
3126f3cdf0SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross  * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross  */
43db2bae30SDana Myers 
44db2bae30SDana Myers #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46db2bae30SDana Myers #include "acparser.h"
47db2bae30SDana Myers #include "acinterp.h"
48db2bae30SDana Myers #include "acevents.h"
49db2bae30SDana Myers #include "amlcode.h"
50db2bae30SDana Myers 
51db2bae30SDana Myers 
52db2bae30SDana Myers #define _COMPONENT          ACPI_EXECUTER
53db2bae30SDana Myers         ACPI_MODULE_NAME    ("exoparg2")
54db2bae30SDana Myers 
55db2bae30SDana Myers 
56db2bae30SDana Myers /*!
57db2bae30SDana Myers  * Naming convention for AML interpreter execution routines.
58db2bae30SDana Myers  *
59db2bae30SDana Myers  * The routines that begin execution of AML opcodes are named with a common
60db2bae30SDana Myers  * convention based upon the number of arguments, the number of target operands,
61db2bae30SDana Myers  * and whether or not a value is returned:
62db2bae30SDana Myers  *
63db2bae30SDana Myers  *      AcpiExOpcode_xA_yT_zR
64db2bae30SDana Myers  *
65db2bae30SDana Myers  * Where:
66db2bae30SDana Myers  *
67db2bae30SDana Myers  * xA - ARGUMENTS:    The number of arguments (input operands) that are
68db2bae30SDana Myers  *                    required for this opcode type (1 through 6 args).
69db2bae30SDana Myers  * yT - TARGETS:      The number of targets (output operands) that are required
70db2bae30SDana Myers  *                    for this opcode type (0, 1, or 2 targets).
71db2bae30SDana Myers  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
72db2bae30SDana Myers  *                    as the function return (0 or 1).
73db2bae30SDana Myers  *
74db2bae30SDana Myers  * The AcpiExOpcode* functions are called via the Dispatcher component with
75db2bae30SDana Myers  * fully resolved operands.
76db2bae30SDana Myers !*/
77db2bae30SDana Myers 
78db2bae30SDana Myers 
79db2bae30SDana Myers /*******************************************************************************
80db2bae30SDana Myers  *
81db2bae30SDana Myers  * FUNCTION:    AcpiExOpcode_2A_0T_0R
82db2bae30SDana Myers  *
83db2bae30SDana Myers  * PARAMETERS:  WalkState           - Current walk state
84db2bae30SDana Myers  *
85db2bae30SDana Myers  * RETURN:      Status
86db2bae30SDana Myers  *
87db2bae30SDana Myers  * DESCRIPTION: Execute opcode with two arguments, no target, and no return
88db2bae30SDana Myers  *              value.
89db2bae30SDana Myers  *
90db2bae30SDana Myers  * ALLOCATION:  Deletes both operands
91db2bae30SDana Myers  *
92db2bae30SDana Myers  ******************************************************************************/
93db2bae30SDana Myers 
94db2bae30SDana Myers ACPI_STATUS
95db2bae30SDana Myers AcpiExOpcode_2A_0T_0R (
96db2bae30SDana Myers     ACPI_WALK_STATE         *WalkState)
97db2bae30SDana Myers {
98db2bae30SDana Myers     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
99db2bae30SDana Myers     ACPI_NAMESPACE_NODE     *Node;
100db2bae30SDana Myers     UINT32                  Value;
101db2bae30SDana Myers     ACPI_STATUS             Status = AE_OK;
102db2bae30SDana Myers 
103db2bae30SDana Myers 
104db2bae30SDana Myers     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R,
105db2bae30SDana Myers             AcpiPsGetOpcodeName (WalkState->Opcode));
106db2bae30SDana Myers 
107db2bae30SDana Myers 
108db2bae30SDana Myers     /* Examine the opcode */
109db2bae30SDana Myers 
110db2bae30SDana Myers     switch (WalkState->Opcode)
111db2bae30SDana Myers     {
112db2bae30SDana Myers     case AML_NOTIFY_OP:         /* Notify (NotifyObject, NotifyValue) */
113db2bae30SDana Myers 
114db2bae30SDana Myers         /* The first operand is a namespace node */
115db2bae30SDana Myers 
116db2bae30SDana Myers         Node = (ACPI_NAMESPACE_NODE *) Operand[0];
117db2bae30SDana Myers 
118db2bae30SDana Myers         /* Second value is the notify value */
119db2bae30SDana Myers 
120db2bae30SDana Myers         Value = (UINT32) Operand[1]->Integer.Value;
121db2bae30SDana Myers 
122db2bae30SDana Myers         /* Are notifies allowed on this object? */
123db2bae30SDana Myers 
124db2bae30SDana Myers         if (!AcpiEvIsNotifyObject (Node))
125db2bae30SDana Myers         {
126db2bae30SDana Myers             ACPI_ERROR ((AE_INFO,
127db2bae30SDana Myers                 "Unexpected notify object type [%s]",
128db2bae30SDana Myers                 AcpiUtGetTypeName (Node->Type)));
129db2bae30SDana Myers 
130db2bae30SDana Myers             Status = AE_AML_OPERAND_TYPE;
131db2bae30SDana Myers             break;
132db2bae30SDana Myers         }
133db2bae30SDana Myers 
134db2bae30SDana Myers         /*
135db2bae30SDana Myers          * Dispatch the notify to the appropriate handler
136db2bae30SDana Myers          * NOTE: the request is queued for execution after this method
137db2bae30SDana Myers          * completes. The notify handlers are NOT invoked synchronously
138db2bae30SDana Myers          * from this thread -- because handlers may in turn run other
139db2bae30SDana Myers          * control methods.
140db2bae30SDana Myers          */
141db2bae30SDana Myers         Status = AcpiEvQueueNotifyRequest (Node, Value);
142db2bae30SDana Myers         break;
143db2bae30SDana Myers 
144db2bae30SDana Myers     default:
145db2bae30SDana Myers 
14626f3cdf0SGordon Ross         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
147db2bae30SDana Myers             WalkState->Opcode));
148db2bae30SDana Myers         Status = AE_AML_BAD_OPCODE;
149db2bae30SDana Myers     }
150db2bae30SDana Myers 
151db2bae30SDana Myers     return_ACPI_STATUS (Status);
152db2bae30SDana Myers }
153db2bae30SDana Myers 
154db2bae30SDana Myers 
155db2bae30SDana Myers /*******************************************************************************
156db2bae30SDana Myers  *
157db2bae30SDana Myers  * FUNCTION:    AcpiExOpcode_2A_2T_1R
158db2bae30SDana Myers  *
159db2bae30SDana Myers  * PARAMETERS:  WalkState           - Current walk state
160db2bae30SDana Myers  *
161db2bae30SDana Myers  * RETURN:      Status
162db2bae30SDana Myers  *
163db2bae30SDana Myers  * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
164db2bae30SDana Myers  *              and one implicit return value.
165db2bae30SDana Myers  *
166db2bae30SDana Myers  ******************************************************************************/
167db2bae30SDana Myers 
168db2bae30SDana Myers ACPI_STATUS
169db2bae30SDana Myers AcpiExOpcode_2A_2T_1R (
170db2bae30SDana Myers     ACPI_WALK_STATE         *WalkState)
171db2bae30SDana Myers {
172db2bae30SDana Myers     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
173db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *ReturnDesc1 = NULL;
174db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *ReturnDesc2 = NULL;
175db2bae30SDana Myers     ACPI_STATUS             Status;
176db2bae30SDana Myers 
177db2bae30SDana Myers 
178db2bae30SDana Myers     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R,
179db2bae30SDana Myers         AcpiPsGetOpcodeName (WalkState->Opcode));
180db2bae30SDana Myers 
181db2bae30SDana Myers 
182db2bae30SDana Myers     /* Execute the opcode */
183db2bae30SDana Myers 
184db2bae30SDana Myers     switch (WalkState->Opcode)
185db2bae30SDana Myers     {
186db2bae30SDana Myers     case AML_DIVIDE_OP:
187db2bae30SDana Myers 
188db2bae30SDana Myers         /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */
189db2bae30SDana Myers 
190db2bae30SDana Myers         ReturnDesc1 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
191db2bae30SDana Myers         if (!ReturnDesc1)
192db2bae30SDana Myers         {
193db2bae30SDana Myers             Status = AE_NO_MEMORY;
194db2bae30SDana Myers             goto Cleanup;
195db2bae30SDana Myers         }
196db2bae30SDana Myers 
197db2bae30SDana Myers         ReturnDesc2 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
198db2bae30SDana Myers         if (!ReturnDesc2)
199db2bae30SDana Myers         {
200db2bae30SDana Myers             Status = AE_NO_MEMORY;
201db2bae30SDana Myers             goto Cleanup;
202db2bae30SDana Myers         }
203db2bae30SDana Myers 
204db2bae30SDana Myers         /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */
205db2bae30SDana Myers 
206*385cc6b4SJerry Jelinek         Status = AcpiUtDivide (
207*385cc6b4SJerry Jelinek             Operand[0]->Integer.Value,
208db2bae30SDana Myers             Operand[1]->Integer.Value,
209db2bae30SDana Myers             &ReturnDesc1->Integer.Value,
210db2bae30SDana Myers             &ReturnDesc2->Integer.Value);
211db2bae30SDana Myers         if (ACPI_FAILURE (Status))
212db2bae30SDana Myers         {
213db2bae30SDana Myers             goto Cleanup;
214db2bae30SDana Myers         }
215db2bae30SDana Myers         break;
216db2bae30SDana Myers 
217db2bae30SDana Myers     default:
218db2bae30SDana Myers 
21926f3cdf0SGordon Ross         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
220db2bae30SDana Myers             WalkState->Opcode));
221*385cc6b4SJerry Jelinek 
222db2bae30SDana Myers         Status = AE_AML_BAD_OPCODE;
223db2bae30SDana Myers         goto Cleanup;
224db2bae30SDana Myers     }
225db2bae30SDana Myers 
226db2bae30SDana Myers     /* Store the results to the target reference operands */
227db2bae30SDana Myers 
228db2bae30SDana Myers     Status = AcpiExStore (ReturnDesc2, Operand[2], WalkState);
229db2bae30SDana Myers     if (ACPI_FAILURE (Status))
230db2bae30SDana Myers     {
231db2bae30SDana Myers         goto Cleanup;
232db2bae30SDana Myers     }
233db2bae30SDana Myers 
234db2bae30SDana Myers     Status = AcpiExStore (ReturnDesc1, Operand[3], WalkState);
235db2bae30SDana Myers     if (ACPI_FAILURE (Status))
236db2bae30SDana Myers     {
237db2bae30SDana Myers         goto Cleanup;
238db2bae30SDana Myers     }
239db2bae30SDana Myers 
240db2bae30SDana Myers Cleanup:
241db2bae30SDana Myers     /*
242db2bae30SDana Myers      * Since the remainder is not returned indirectly, remove a reference to
243db2bae30SDana Myers      * it. Only the quotient is returned indirectly.
244db2bae30SDana Myers      */
245db2bae30SDana Myers     AcpiUtRemoveReference (ReturnDesc2);
246db2bae30SDana Myers 
247db2bae30SDana Myers     if (ACPI_FAILURE (Status))
248db2bae30SDana Myers     {
249db2bae30SDana Myers         /* Delete the return object */
250db2bae30SDana Myers 
251db2bae30SDana Myers         AcpiUtRemoveReference (ReturnDesc1);
252db2bae30SDana Myers     }
253db2bae30SDana Myers 
254db2bae30SDana Myers     /* Save return object (the remainder) on success */
255db2bae30SDana Myers 
256db2bae30SDana Myers     else
257db2bae30SDana Myers     {
258db2bae30SDana Myers         WalkState->ResultObj = ReturnDesc1;
259db2bae30SDana Myers     }
260db2bae30SDana Myers 
261db2bae30SDana Myers     return_ACPI_STATUS (Status);
262db2bae30SDana Myers }
263db2bae30SDana Myers 
264db2bae30SDana Myers 
265db2bae30SDana Myers /*******************************************************************************
266db2bae30SDana Myers  *
267db2bae30SDana Myers  * FUNCTION:    AcpiExOpcode_2A_1T_1R
268db2bae30SDana Myers  *
269db2bae30SDana Myers  * PARAMETERS:  WalkState           - Current walk state
270db2bae30SDana Myers  *
271db2bae30SDana Myers  * RETURN:      Status
272db2bae30SDana Myers  *
273db2bae30SDana Myers  * DESCRIPTION: Execute opcode with two arguments, one target, and a return
274db2bae30SDana Myers  *              value.
275db2bae30SDana Myers  *
276db2bae30SDana Myers  ******************************************************************************/
277db2bae30SDana Myers 
278db2bae30SDana Myers ACPI_STATUS
279db2bae30SDana Myers AcpiExOpcode_2A_1T_1R (
280db2bae30SDana Myers     ACPI_WALK_STATE         *WalkState)
281db2bae30SDana Myers {
282db2bae30SDana Myers     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
283db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
28426f3cdf0SGordon Ross     UINT64                  Index;
285db2bae30SDana Myers     ACPI_STATUS             Status = AE_OK;
286*385cc6b4SJerry Jelinek     ACPI_SIZE               Length = 0;
287db2bae30SDana Myers 
288db2bae30SDana Myers 
289db2bae30SDana Myers     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R,
290db2bae30SDana Myers         AcpiPsGetOpcodeName (WalkState->Opcode));
291db2bae30SDana Myers 
292db2bae30SDana Myers 
293db2bae30SDana Myers     /* Execute the opcode */
294db2bae30SDana Myers 
295db2bae30SDana Myers     if (WalkState->OpInfo->Flags & AML_MATH)
296db2bae30SDana Myers     {
297db2bae30SDana Myers         /* All simple math opcodes (add, etc.) */
298db2bae30SDana Myers 
299db2bae30SDana Myers         ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
300db2bae30SDana Myers         if (!ReturnDesc)
301db2bae30SDana Myers         {
302db2bae30SDana Myers             Status = AE_NO_MEMORY;
303db2bae30SDana Myers             goto Cleanup;
304db2bae30SDana Myers         }
305db2bae30SDana Myers 
306*385cc6b4SJerry Jelinek         ReturnDesc->Integer.Value = AcpiExDoMathOp (
307*385cc6b4SJerry Jelinek             WalkState->Opcode,
308db2bae30SDana Myers             Operand[0]->Integer.Value,
309db2bae30SDana Myers             Operand[1]->Integer.Value);
310db2bae30SDana Myers         goto StoreResultToTarget;
311db2bae30SDana Myers     }
312db2bae30SDana Myers 
313db2bae30SDana Myers     switch (WalkState->Opcode)
314db2bae30SDana Myers     {
315db2bae30SDana Myers     case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */
316db2bae30SDana Myers 
317db2bae30SDana Myers         ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
318db2bae30SDana Myers         if (!ReturnDesc)
319db2bae30SDana Myers         {
320db2bae30SDana Myers             Status = AE_NO_MEMORY;
321db2bae30SDana Myers             goto Cleanup;
322db2bae30SDana Myers         }
323db2bae30SDana Myers 
324db2bae30SDana Myers         /* ReturnDesc will contain the remainder */
325db2bae30SDana Myers 
326*385cc6b4SJerry Jelinek         Status = AcpiUtDivide (
327*385cc6b4SJerry Jelinek             Operand[0]->Integer.Value,
328db2bae30SDana Myers             Operand[1]->Integer.Value,
329db2bae30SDana Myers             NULL,
330db2bae30SDana Myers             &ReturnDesc->Integer.Value);
331db2bae30SDana Myers         break;
332db2bae30SDana Myers 
333db2bae30SDana Myers     case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
334db2bae30SDana Myers 
335*385cc6b4SJerry Jelinek         Status = AcpiExDoConcatenate (
336*385cc6b4SJerry Jelinek             Operand[0], Operand[1], &ReturnDesc, WalkState);
337db2bae30SDana Myers         break;
338db2bae30SDana Myers 
339db2bae30SDana Myers     case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */
340db2bae30SDana Myers         /*
341db2bae30SDana Myers          * Input object is guaranteed to be a buffer at this point (it may have
342db2bae30SDana Myers          * been converted.)  Copy the raw buffer data to a new object of
343db2bae30SDana Myers          * type String.
344db2bae30SDana Myers          */
345db2bae30SDana Myers 
346db2bae30SDana Myers         /*
347db2bae30SDana Myers          * Get the length of the new string. It is the smallest of:
348db2bae30SDana Myers          * 1) Length of the input buffer
349db2bae30SDana Myers          * 2) Max length as specified in the ToString operator
350db2bae30SDana Myers          * 3) Length of input buffer up to a zero byte (null terminator)
351db2bae30SDana Myers          *
352db2bae30SDana Myers          * NOTE: A length of zero is ok, and will create a zero-length, null
353db2bae30SDana Myers          *       terminated string.
354db2bae30SDana Myers          */
355db2bae30SDana Myers         while ((Length < Operand[0]->Buffer.Length) &&
356db2bae30SDana Myers                (Length < Operand[1]->Integer.Value) &&
357db2bae30SDana Myers                (Operand[0]->Buffer.Pointer[Length]))
358db2bae30SDana Myers         {
359db2bae30SDana Myers             Length++;
360db2bae30SDana Myers         }
361db2bae30SDana Myers 
362db2bae30SDana Myers         /* Allocate a new string object */
363db2bae30SDana Myers 
364db2bae30SDana Myers         ReturnDesc = AcpiUtCreateStringObject (Length);
365db2bae30SDana Myers         if (!ReturnDesc)
366db2bae30SDana Myers         {
367db2bae30SDana Myers             Status = AE_NO_MEMORY;
368db2bae30SDana Myers             goto Cleanup;
369db2bae30SDana Myers         }
370db2bae30SDana Myers 
371db2bae30SDana Myers         /*
372db2bae30SDana Myers          * Copy the raw buffer data with no transform.
373db2bae30SDana Myers          * (NULL terminated already)
374db2bae30SDana Myers          */
375*385cc6b4SJerry Jelinek         memcpy (ReturnDesc->String.Pointer,
376db2bae30SDana Myers             Operand[0]->Buffer.Pointer, Length);
377db2bae30SDana Myers         break;
378db2bae30SDana Myers 
379db2bae30SDana Myers     case AML_CONCAT_RES_OP:
380db2bae30SDana Myers 
381db2bae30SDana Myers         /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */
382db2bae30SDana Myers 
383*385cc6b4SJerry Jelinek         Status = AcpiExConcatTemplate (
384*385cc6b4SJerry Jelinek             Operand[0], Operand[1], &ReturnDesc, WalkState);
385db2bae30SDana Myers         break;
386db2bae30SDana Myers 
387db2bae30SDana Myers     case AML_INDEX_OP:              /* Index (Source Index Result) */
388db2bae30SDana Myers 
389db2bae30SDana Myers         /* Create the internal return object */
390db2bae30SDana Myers 
391db2bae30SDana Myers         ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
392db2bae30SDana Myers         if (!ReturnDesc)
393db2bae30SDana Myers         {
394db2bae30SDana Myers             Status = AE_NO_MEMORY;
395db2bae30SDana Myers             goto Cleanup;
396db2bae30SDana Myers         }
397db2bae30SDana Myers 
398db2bae30SDana Myers         /* Initialize the Index reference object */
399db2bae30SDana Myers 
400db2bae30SDana Myers         Index = Operand[1]->Integer.Value;
401db2bae30SDana Myers         ReturnDesc->Reference.Value = (UINT32) Index;
402db2bae30SDana Myers         ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX;
403db2bae30SDana Myers 
404db2bae30SDana Myers         /*
405db2bae30SDana Myers          * At this point, the Source operand is a String, Buffer, or Package.
406db2bae30SDana Myers          * Verify that the index is within range.
407db2bae30SDana Myers          */
408aa2aa9a6SDana Myers         switch ((Operand[0])->Common.Type)
409db2bae30SDana Myers         {
410db2bae30SDana Myers         case ACPI_TYPE_STRING:
411db2bae30SDana Myers 
412db2bae30SDana Myers             if (Index >= Operand[0]->String.Length)
413db2bae30SDana Myers             {
414*385cc6b4SJerry Jelinek                 Length = Operand[0]->String.Length;
415db2bae30SDana Myers                 Status = AE_AML_STRING_LIMIT;
416db2bae30SDana Myers             }
417db2bae30SDana Myers 
418db2bae30SDana Myers             ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
419*385cc6b4SJerry Jelinek             ReturnDesc->Reference.IndexPointer =
420*385cc6b4SJerry Jelinek                 &(Operand[0]->Buffer.Pointer [Index]);
421db2bae30SDana Myers             break;
422db2bae30SDana Myers 
423db2bae30SDana Myers         case ACPI_TYPE_BUFFER:
424db2bae30SDana Myers 
425db2bae30SDana Myers             if (Index >= Operand[0]->Buffer.Length)
426db2bae30SDana Myers             {
427*385cc6b4SJerry Jelinek                 Length = Operand[0]->Buffer.Length;
428db2bae30SDana Myers                 Status = AE_AML_BUFFER_LIMIT;
429db2bae30SDana Myers             }
430db2bae30SDana Myers 
431db2bae30SDana Myers             ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
432*385cc6b4SJerry Jelinek             ReturnDesc->Reference.IndexPointer =
433*385cc6b4SJerry Jelinek                 &(Operand[0]->Buffer.Pointer [Index]);
434db2bae30SDana Myers             break;
435db2bae30SDana Myers 
436db2bae30SDana Myers         case ACPI_TYPE_PACKAGE:
437db2bae30SDana Myers 
438db2bae30SDana Myers             if (Index >= Operand[0]->Package.Count)
439db2bae30SDana Myers             {
440*385cc6b4SJerry Jelinek                 Length = Operand[0]->Package.Count;
441db2bae30SDana Myers                 Status = AE_AML_PACKAGE_LIMIT;
442db2bae30SDana Myers             }
443db2bae30SDana Myers 
444db2bae30SDana Myers             ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE;
445*385cc6b4SJerry Jelinek             ReturnDesc->Reference.Where =
446*385cc6b4SJerry Jelinek                 &Operand[0]->Package.Elements [Index];
447db2bae30SDana Myers             break;
448db2bae30SDana Myers 
449db2bae30SDana Myers         default:
450db2bae30SDana Myers 
451db2bae30SDana Myers             Status = AE_AML_INTERNAL;
452db2bae30SDana Myers             goto Cleanup;
453db2bae30SDana Myers         }
454db2bae30SDana Myers 
455db2bae30SDana Myers         /* Failure means that the Index was beyond the end of the object */
456db2bae30SDana Myers 
457db2bae30SDana Myers         if (ACPI_FAILURE (Status))
458db2bae30SDana Myers         {
459db2bae30SDana Myers             ACPI_EXCEPTION ((AE_INFO, Status,
460*385cc6b4SJerry Jelinek                 "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
461*385cc6b4SJerry Jelinek                 ACPI_FORMAT_UINT64 (Index), (UINT32) Length));
462db2bae30SDana Myers             goto Cleanup;
463db2bae30SDana Myers         }
464db2bae30SDana Myers 
465db2bae30SDana Myers         /*
466db2bae30SDana Myers          * Save the target object and add a reference to it for the life
467db2bae30SDana Myers          * of the index
468db2bae30SDana Myers          */
469db2bae30SDana Myers         ReturnDesc->Reference.Object = Operand[0];
470db2bae30SDana Myers         AcpiUtAddReference (Operand[0]);
471db2bae30SDana Myers 
472db2bae30SDana Myers         /* Store the reference to the Target */
473db2bae30SDana Myers 
474db2bae30SDana Myers         Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);
475db2bae30SDana Myers 
476db2bae30SDana Myers         /* Return the reference */
477db2bae30SDana Myers 
478db2bae30SDana Myers         WalkState->ResultObj = ReturnDesc;
479db2bae30SDana Myers         goto Cleanup;
480db2bae30SDana Myers 
481db2bae30SDana Myers     default:
482db2bae30SDana Myers 
48326f3cdf0SGordon Ross         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
484db2bae30SDana Myers             WalkState->Opcode));
485db2bae30SDana Myers         Status = AE_AML_BAD_OPCODE;
486db2bae30SDana Myers         break;
487db2bae30SDana Myers     }
488db2bae30SDana Myers 
489db2bae30SDana Myers 
490db2bae30SDana Myers StoreResultToTarget:
491db2bae30SDana Myers 
492db2bae30SDana Myers     if (ACPI_SUCCESS (Status))
493db2bae30SDana Myers     {
494db2bae30SDana Myers         /*
495db2bae30SDana Myers          * Store the result of the operation (which is now in ReturnDesc) into
496db2bae30SDana Myers          * the Target descriptor.
497db2bae30SDana Myers          */
498db2bae30SDana Myers         Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);
499db2bae30SDana Myers         if (ACPI_FAILURE (Status))
500db2bae30SDana Myers         {
501db2bae30SDana Myers             goto Cleanup;
502db2bae30SDana Myers         }
503db2bae30SDana Myers 
504db2bae30SDana Myers         if (!WalkState->ResultObj)
505db2bae30SDana Myers         {
506db2bae30SDana Myers             WalkState->ResultObj = ReturnDesc;
507db2bae30SDana Myers         }
508db2bae30SDana Myers     }
509db2bae30SDana Myers 
510db2bae30SDana Myers 
511db2bae30SDana Myers Cleanup:
512db2bae30SDana Myers 
513db2bae30SDana Myers     /* Delete return object on error */
514db2bae30SDana Myers 
515db2bae30SDana Myers     if (ACPI_FAILURE (Status))
516db2bae30SDana Myers     {
517db2bae30SDana Myers         AcpiUtRemoveReference (ReturnDesc);
518db2bae30SDana Myers         WalkState->ResultObj = NULL;
519db2bae30SDana Myers     }
520db2bae30SDana Myers 
521db2bae30SDana Myers     return_ACPI_STATUS (Status);
522db2bae30SDana Myers }
523db2bae30SDana Myers 
524db2bae30SDana Myers 
525db2bae30SDana Myers /*******************************************************************************
526db2bae30SDana Myers  *
527db2bae30SDana Myers  * FUNCTION:    AcpiExOpcode_2A_0T_1R
528db2bae30SDana Myers  *
529db2bae30SDana Myers  * PARAMETERS:  WalkState           - Current walk state
530db2bae30SDana Myers  *
531db2bae30SDana Myers  * RETURN:      Status
532db2bae30SDana Myers  *
533db2bae30SDana Myers  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
534db2bae30SDana Myers  *
535db2bae30SDana Myers  ******************************************************************************/
536db2bae30SDana Myers 
537db2bae30SDana Myers ACPI_STATUS
538db2bae30SDana Myers AcpiExOpcode_2A_0T_1R (
539db2bae30SDana Myers     ACPI_WALK_STATE         *WalkState)
540db2bae30SDana Myers {
541db2bae30SDana Myers     ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
542db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
543db2bae30SDana Myers     ACPI_STATUS             Status = AE_OK;
544db2bae30SDana Myers     BOOLEAN                 LogicalResult = FALSE;
545db2bae30SDana Myers 
546db2bae30SDana Myers 
547db2bae30SDana Myers     ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R,
548db2bae30SDana Myers         AcpiPsGetOpcodeName (WalkState->Opcode));
549db2bae30SDana Myers 
550db2bae30SDana Myers 
551db2bae30SDana Myers     /* Create the internal return object */
552db2bae30SDana Myers 
553db2bae30SDana Myers     ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
554db2bae30SDana Myers     if (!ReturnDesc)
555db2bae30SDana Myers     {
556db2bae30SDana Myers         Status = AE_NO_MEMORY;
557db2bae30SDana Myers         goto Cleanup;
558db2bae30SDana Myers     }
559db2bae30SDana Myers 
560db2bae30SDana Myers     /* Execute the Opcode */
561db2bae30SDana Myers 
562db2bae30SDana Myers     if (WalkState->OpInfo->Flags & AML_LOGICAL_NUMERIC)
563db2bae30SDana Myers     {
564db2bae30SDana Myers         /* LogicalOp  (Operand0, Operand1) */
565db2bae30SDana Myers 
566db2bae30SDana Myers         Status = AcpiExDoLogicalNumericOp (WalkState->Opcode,
567db2bae30SDana Myers             Operand[0]->Integer.Value, Operand[1]->Integer.Value,
568db2bae30SDana Myers             &LogicalResult);
569db2bae30SDana Myers         goto StoreLogicalResult;
570db2bae30SDana Myers     }
571db2bae30SDana Myers     else if (WalkState->OpInfo->Flags & AML_LOGICAL)
572db2bae30SDana Myers     {
573db2bae30SDana Myers         /* LogicalOp  (Operand0, Operand1) */
574db2bae30SDana Myers 
575db2bae30SDana Myers         Status = AcpiExDoLogicalOp (WalkState->Opcode, Operand[0],
576db2bae30SDana Myers             Operand[1], &LogicalResult);
577db2bae30SDana Myers         goto StoreLogicalResult;
578db2bae30SDana Myers     }
579db2bae30SDana Myers 
580db2bae30SDana Myers     switch (WalkState->Opcode)
581db2bae30SDana Myers     {
582db2bae30SDana Myers     case AML_ACQUIRE_OP:            /* Acquire (MutexObject, Timeout) */
583db2bae30SDana Myers 
584db2bae30SDana Myers         Status = AcpiExAcquireMutex (Operand[1], Operand[0], WalkState);
585db2bae30SDana Myers         if (Status == AE_TIME)
586db2bae30SDana Myers         {
587db2bae30SDana Myers             LogicalResult = TRUE;       /* TRUE = Acquire timed out */
588db2bae30SDana Myers             Status = AE_OK;
589db2bae30SDana Myers         }
590db2bae30SDana Myers         break;
591db2bae30SDana Myers 
592db2bae30SDana Myers 
593db2bae30SDana Myers     case AML_WAIT_OP:               /* Wait (EventObject, Timeout) */
594db2bae30SDana Myers 
595db2bae30SDana Myers         Status = AcpiExSystemWaitEvent (Operand[1], Operand[0]);
596db2bae30SDana Myers         if (Status == AE_TIME)
597db2bae30SDana Myers         {
598db2bae30SDana Myers             LogicalResult = TRUE;       /* TRUE, Wait timed out */
599db2bae30SDana Myers             Status = AE_OK;
600db2bae30SDana Myers         }
601db2bae30SDana Myers         break;
602db2bae30SDana Myers 
603db2bae30SDana Myers     default:
604db2bae30SDana Myers 
60526f3cdf0SGordon Ross         ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
606db2bae30SDana Myers             WalkState->Opcode));
607*385cc6b4SJerry Jelinek 
608db2bae30SDana Myers         Status = AE_AML_BAD_OPCODE;
609db2bae30SDana Myers         goto Cleanup;
610db2bae30SDana Myers     }
611db2bae30SDana Myers 
612db2bae30SDana Myers 
613db2bae30SDana Myers StoreLogicalResult:
614db2bae30SDana Myers     /*
615db2bae30SDana Myers      * Set return value to according to LogicalResult. logical TRUE (all ones)
616db2bae30SDana Myers      * Default is FALSE (zero)
617db2bae30SDana Myers      */
618db2bae30SDana Myers     if (LogicalResult)
619db2bae30SDana Myers     {
62026f3cdf0SGordon Ross         ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
621db2bae30SDana Myers     }
622db2bae30SDana Myers 
623db2bae30SDana Myers Cleanup:
624db2bae30SDana Myers 
625db2bae30SDana Myers     /* Delete return object on error */
626db2bae30SDana Myers 
627db2bae30SDana Myers     if (ACPI_FAILURE (Status))
628db2bae30SDana Myers     {
629db2bae30SDana Myers         AcpiUtRemoveReference (ReturnDesc);
630db2bae30SDana Myers     }
631db2bae30SDana Myers 
632db2bae30SDana Myers     /* Save return object on success */
633db2bae30SDana Myers 
634db2bae30SDana Myers     else
635db2bae30SDana Myers     {
636db2bae30SDana Myers         WalkState->ResultObj = ReturnDesc;
637db2bae30SDana Myers     }
638db2bae30SDana Myers 
639db2bae30SDana Myers     return_ACPI_STATUS (Status);
640db2bae30SDana Myers }
641